New version of ash. From FreeBSD 5.4 via Minix-vmd.

This commit is contained in:
Philip Homburg 2006-05-23 12:59:34 +00:00
parent 3ea083b8d4
commit 7aa4c9ec2f
84 changed files with 8833 additions and 5442 deletions

View file

@ -1,41 +1,61 @@
# Makefile for ash. # 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 \ 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 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 \ 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 \ 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
# LEX=flex
# Set READLINE in shell.h and add -ledit to LIBS if you want to use the YACC=yacc
# editline package by Simmule Turner and Rich Salz. (The big, bloated .c.o:
# and GPL contaminated FSF readline should work too.) $(CC) $(CFLAGS) -c $< -o $@
#
CPPFLAGS= -DSHELL -I. -D_MINIX -D_POSIX_SOURCE # Enable this line to disable command line editing
CFLAGS= -wo -i $(CPPFLAGS) #EDIT=-DNO_HISTORY
LIBS= -ledit # Enable this line to use the editline library instead of libedit
CC = exec cc 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) \ CLEANFILES= $(OBJS) \
builtins.c builtins.h init.c mkinit mknodes mksignames mksyntax \ arith.c arith_y.h arith_lex.c builtins.c builtins.h init.c \
nodes.c nodes.h signames.c signames.h syntax.c syntax.h token.def \ mkinit mknodes mksignames mksyntax \
nodes.c nodes.h signames.c signames.h syntax.c syntax.h token.h \
bltin/operators.h bltin/operators.c bltin/operators.h bltin/operators.c
all: sh all: sh
sh: $(OBJS) sh: $(OBJS)
$(CC) $(CFLAGS) -o sh $(OBJS) $(LIBS) $(CC) $(CFLAGS) -fnone -o sh $(OBJS) $(LIBS)
install -S 100k sh
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 /usr/bin/ash: sh
install -cs -o bin $? $@ install -c $? $@
/usr/bin/sh: /usr/bin/ash /usr/bin/sh: /usr/bin/ash
install -l $? $@ install -l $? $@
@ -43,8 +63,14 @@ install: /usr/bin/ash /usr/bin/sh /bin/sh /bin/bigsh
/bin/sh: /usr/bin/ash /bin/sh: /usr/bin/ash
install -lcs $? $@ install -lcs $? $@
/bin/bigsh: /usr/bin/ash /usr/man/man1/ash.1: sh.1
install -S 1500000 -lcs $? $@ install -lc $? $@
/usr/man/man1/echo.1: bltin/echo.1
install -lc $? $@
/usr/man/man1/expr.1: bltin/expr.1
install -lc $? $@
clean: clean:
rm -f $(CLEANFILES) sh core rm -f $(CLEANFILES) sh core
@ -54,11 +80,18 @@ parser.o: token.def
token.def: mktokens token.def: mktokens
sh mktokens sh mktokens
builtins.c builtins.h: builtins.table shell.h arith.c: arith.y
sh mkbuiltins shell.h builtins.table $(YACC) -d $?
mv y.tab.c $@
mv y.tab.h arith_y.h
init.o: mkinit $(SRCS) arith_lex.c: arith_lex.l
./mkinit '$(CC) -c $(CFLAGS) init.c' $(SRCS)
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 mkinit: mkinit.c
$(CC) $(CFLAGS) mkinit.c -o $@ $(CC) $(CFLAGS) mkinit.c -o $@
@ -81,20 +114,8 @@ syntax.c syntax.h: mksyntax
mksyntax: mksyntax.c parser.h mksyntax: mksyntax.c parser.h
$(CC) $(CFLAGS) mksyntax.c -o $@ $(CC) $(CFLAGS) mksyntax.c -o $@
bltin/operators.h: bltin/mkexpr bltin/binary_op bltin/unary_op bltin/operators.h: bltin/mkexpr bltin/unary_op bltin/binary_op
cd bltin && sh mkexpr cd bltin && sh mkexpr unary_op binary_op
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
# Dependencies you say? This will have to do. # Dependencies you say? This will have to do.
$(OBJS): error.h eval.h exec.h expand.h init.h input.h \ $(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 builtins.h nodes.h signames.h syntax.h
bltin/expr.o bltin/operators.o: bltin/operators.h bltin/expr.o bltin/operators.o: bltin/operators.h
#
# $PchId: Makefile,v 1.4 2006/05/22 12:40:46 philip Exp $

View file

@ -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 A Tour through Ash
@ -20,7 +29,7 @@ programs is:
mknodes nodetypes nodes.h nodes.c mknodes nodetypes nodes.h nodes.c
mksignames - signames.h signames.c mksignames - signames.h signames.c
mksyntax - syntax.h syntax.c mksyntax - syntax.h syntax.c
mktokens - token.def mktokens - token.h
bltin/mkexpr unary_op binary_op operators.h operators.c bltin/mkexpr unary_op binary_op operators.h operators.c
There are undoubtedly too many of these. Mkinit searches all the 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 number of arguments. Defining DEBUG also causes the shell to
generate a core dump if it is sent a quit signal. The tracing generate a core dump if it is sent a quit signal. The tracing
code is in show.c. 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
View 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
View 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
View 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
View 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
View 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
View 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 $
*/

View file

@ -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 * 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 * shell. If SHELL is defined, we try to map the standard UNIX library
* routines to ash routines using defines. * 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 "../shell.h"
#include "../mystring.h" #include "../mystring.h"
#ifdef SHELL #ifdef SHELL
#include "builtins.h"
#include "../output.h" #include "../output.h"
#undef stdout
#define stdout out1 #define stdout out1
#undef stderr
#define stderr out2 #define stderr out2
#define printf out1fmt #define printf out1fmt
#undef putc
#define putc(c, file) outc(c, file) #define putc(c, file) outc(c, file)
#undef putchar
#define putchar(c) out1c(c) #define putchar(c) out1c(c)
#define fprintf outfmt #define fprintf outfmt
#define fputs outstr #define fputs outstr
#define fflush flushout #define fflush flushout
#define INITARGS(argv) #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 #else
#undef NULL #undef NULL
#include <stdio.h> #include <stdio.h>
@ -28,13 +80,12 @@
#define INITARGS(argv) if ((commandname = argv[0]) == NULL) {fputs("Argc is zero\n", stderr); exit(2);} else #define INITARGS(argv) if ((commandname = argv[0]) == NULL) {fputs("Argc is zero\n", stderr); exit(2);} else
#endif #endif
#ifdef __STDC__
pointer stalloc(int); pointer stalloc(int);
void error(char *, ...); void error(const char *, ...);
#else
pointer stalloc();
void error();
#endif
extern char *commandname; extern char *commandname;
/*
* $PchId: bltin.h,v 1.4 2006/03/29 11:39:00 philip Exp $
*/

View file

@ -1,22 +1,66 @@
/* /*-
* 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 code is derived from software contributed to Berkeley by
* This file is part of ash, which is distributed under the terms specified * Kenneth Almquist.
* by the Ash General Public License. See the file named LICENSE. *
* 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" #include "bltin.h"
#ifndef MINIX
/* #define eflag 1 */
#else
#undef eflag #undef eflag
#endif
int
main(argc, argv) char **argv; { echocmd(argc, argv)
register char **ap; int argc;
register char *p; char **argv;
register char c; {
char **ap;
char *p;
char c;
int count; int count;
int nflag = 0; int nflag = 0;
#ifndef eflag #ifndef eflag
@ -27,9 +71,11 @@ main(argc, argv) char **argv; {
if (argc) if (argc)
ap++; ap++;
if ((p = *ap) != NULL) { if ((p = *ap) != NULL) {
#ifdef MINIX
if (equal(p, "--")) { if (equal(p, "--")) {
ap++; ap++;
} }
#endif
if (equal(p, "-n")) { if (equal(p, "-n")) {
nflag++; nflag++;
ap++; ap++;
@ -44,8 +90,10 @@ main(argc, argv) char **argv; {
while ((c = *p++) != '\0') { while ((c = *p++) != '\0') {
if (c == '\\' && eflag) { if (c == '\\' && eflag) {
switch (*p++) { switch (*p++) {
case 'a': c = '\a'; break;
case 'b': c = '\b'; break; case 'b': c = '\b'; break;
case 'c': return 0; /* exit */ case 'c': return 0; /* exit */
case 'e': c = '\033'; break;
case 'f': c = '\f'; break; case 'f': c = '\f'; break;
case 'n': c = '\n'; break; case 'n': c = '\n'; break;
case 'r': c = '\r'; break; case 'r': c = '\r'; break;
@ -72,3 +120,7 @@ main(argc, argv) char **argv; {
putchar('\n'); putchar('\n');
return 0; return 0;
} }
/*
* $PchId: echo.c,v 1.5 2006/05/23 12:05:56 philip Exp $
*/

View file

@ -7,17 +7,14 @@
*/ */
#define main exprcmd
#include "bltin.h" #include "bltin.h"
#include "operators.h" #include "operators.h"
#include <regex.h>
#include <sys/types.h> #include <sys/types.h>
#include <sys/stat.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 STACKSIZE 12
#define NESTINCR 16 #define NESTINCR 16
@ -50,7 +47,6 @@ struct operator {
struct filestat { struct filestat {
int op; /* OP_FILE or OP_LFILE */
char *name; /* name of file */ char *name; /* name of file */
int rcode; /* return code from stat */ int rcode; /* return code from stat */
struct stat stat; /* status info on file */ struct stat stat; /* status info on file */
@ -63,24 +59,18 @@ extern short number_parens; /* number of \( \) pairs */
#ifdef __STDC__ #ifdef __STDC__
int expr_is_false(struct value *); static int expr_is_false(struct value *);
void expr_operator(int, struct value *, struct filestat *); static void expr_operator(int, struct value *, struct filestat *);
int lookup_op(char *, char *const*); static 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 *);
#else #else
int expr_is_false(); static int expr_is_false();
void expr_operator(); static void expr_operator();
int lookup_op(); static int lookup_op();
char *re_compile(); /* defined in regexp.c */
int re_match(); /* defined in regexp.c */
long atol();
#endif #endif
main(argc, argv) char **argv; { exprcmd(argc, argv) char **argv; {
char **ap; char **ap;
char *opname; char *opname;
char c; char c;
@ -146,6 +136,13 @@ overflow: error("Expression too complex");
continue; continue;
} else { } else {
if (opname[0] == '\'') {
for (p = opname ; *++p != '\0' ; );
if (--p > opname && *p == '\'') {
*p = '\0';
opname++;
}
}
valsp->type = STRING; valsp->type = STRING;
valsp->u.string = opname; valsp->u.string = opname;
valsp++; valsp++;
@ -193,19 +190,11 @@ overflow: error("Expression too complex");
valsp->u.string = ""; valsp->u.string = "";
} }
valsp->type = STRING; valsp->type = STRING;
if (c >= OP_FILE if (c == OP_FILE
&& (fs.op != c && (fs.name == NULL
|| fs.name == NULL
|| ! equal(fs.name, valsp->u.string))) { || ! equal(fs.name, valsp->u.string))) {
fs.op = c;
fs.name = valsp->u.string; fs.name = valsp->u.string;
if (c == OP_FILE) { fs.rcode = stat(valsp->u.string, &fs.stat);
fs.rcode = stat(valsp->u.string,
&fs.stat);
} else {
fs.rcode = lstat(valsp->u.string,
&fs.stat);
}
} }
} }
if (binary < FIRST_BINARY_OP) if (binary < FIRST_BINARY_OP)
@ -250,7 +239,7 @@ done:
} }
int static int
expr_is_false(val) expr_is_false(val)
struct value *val; struct value *val;
{ {
@ -274,14 +263,16 @@ expr_is_false(val)
* to stat, to avoid repeated stat calls on the same file. * to stat, to avoid repeated stat calls on the same file.
*/ */
void static void
expr_operator(op, sp, fs) expr_operator(op, sp, fs)
int op; int op;
struct value *sp; struct value *sp;
struct filestat *fs; struct filestat *fs;
{ {
int i; int i, r;
struct stat st1, st2; struct stat st1, st2;
regex_t pat;
regmatch_t rm[2];
switch (op) { switch (op) {
case NOT: case NOT:
@ -343,16 +334,16 @@ filebit:
if (fs->stat.st_mode & i && fs->rcode >= 0) if (fs->stat.st_mode & i && fs->rcode >= 0)
goto true; goto true;
goto false; goto false;
case ISSLINK:
if (lstat(fs->name, &st1) == -1)
goto false;
if (S_ISLNK(st1.st_mode))
goto true;
goto false;
case ISSIZE: case ISSIZE:
sp->u.num = fs->rcode >= 0? fs->stat.st_size : 0L; sp->u.num = fs->rcode >= 0? fs->stat.st_size : 0L;
sp->type = INTEGER; sp->type = INTEGER;
break; 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: case NEWER:
if (stat(sp->u.string, &st1) != 0) { if (stat(sp->u.string, &st1) != 0) {
sp->u.num = 0; sp->u.num = 0;
@ -439,19 +430,21 @@ filebit:
break; break;
case MATCHPAT: case MATCHPAT:
{ {
char *pat; r = regcomp(&pat, (sp + 1)->u.string, 0);
if (r)
pat = re_compile((sp + 1)->u.string); error("Bad regular expression");
if (re_match(pat, sp->u.string)) { if (regexec(&pat, sp->u.string, 2, rm, 0) == 0 &&
if (number_parens > 0) { rm[0].rm_so == 0)
sp->u.string = match_begin[1]; {
sp->u.string[match_length[1]] = '\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 { } else {
sp->u.num = match_length[0]; sp->u.num = rm[0].rm_eo;
sp->type = INTEGER; sp->type = INTEGER;
} }
} else { } else {
if (number_parens > 0) { if (pat.re_nsub > 0) {
sp->u.string[0] = '\0'; sp->u.string[0] = '\0';
} else { } else {
sp->u.num = 0; sp->u.num = 0;
@ -464,7 +457,7 @@ filebit:
} }
int static int
lookup_op(name, table) lookup_op(name, table)
char *name; char *name;
char *const*table; char *const*table;

View file

@ -5,21 +5,28 @@
# All calls to awk removed, because Minix bawk is deficient. (kjb) # 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 exec > operators.h
i=0 i=0
sed -e '/^[^#]/!d' unary_op binary_op | while read line sed -e '/^[^#]/!d' "$unary_op" "$binary_op" | while read line
do do
set -$- $line set -$- $line
echo "#define $1 $i" echo "#define $1 $i"
i=`expr $i + 1` i=`expr $i + 1`
done done
echo 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 ' echo '
#define OP_INT 1 /* arguments to operator are integer */ #define OP_INT 1 /* arguments to operator are integer */
#define OP_STRING 2 /* arguments to operator are string */ #define OP_STRING 2 /* arguments to operator are string */
#define OP_FILE 3 /* argument is a file name */ #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 unary_op[];
extern char *const binary_op[]; extern char *const binary_op[];
@ -31,14 +38,15 @@ echo '/*
* Operators used in the expr/test command. * Operators used in the expr/test command.
*/ */
#include "../shell.h" #include <stddef.h>
#include "shell.h"
#include "operators.h" #include "operators.h"
char *const unary_op[] = {' char *const unary_op[] = {'
sed -e '/^[^#]/!d sed -e '/^[^#]/!d
s/[ ][ ]*/ /g s/[ ][ ]*/ /g
s/^[^ ][^ ]* \([^ ][^ ]*\).*/ "\1",/ s/^[^ ][^ ]* \([^ ][^ ]*\).*/ "\1",/
' unary_op ' "$unary_op"
echo ' NULL echo ' NULL
}; };
@ -46,7 +54,7 @@ char *const binary_op[] = {'
sed -e '/^[^#]/!d sed -e '/^[^#]/!d
s/[ ][ ]*/ /g s/[ ][ ]*/ /g
s/^[^ ][^ ]* \([^ ][^ ]*\).*/ "\1",/ s/^[^ ][^ ]* \([^ ][^ ]*\).*/ "\1",/
' binary_op ' "$binary_op"
echo ' NULL echo ' NULL
}; };
@ -54,7 +62,7 @@ const char op_priority[] = {'
sed -e '/^[^#]/!d sed -e '/^[^#]/!d
s/[ ][ ]*/ /g s/[ ][ ]*/ /g
s/^[^ ][^ ]* [^ ][^ ]* \([^ ][^ ]*\).*/ \1,/ s/^[^ ][^ ]* [^ ][^ ]* \([^ ][^ ]*\).*/ \1,/
' unary_op binary_op ' "$unary_op" "$binary_op"
echo '}; echo '};
const char op_argflag[] = {' const char op_argflag[] = {'
@ -62,5 +70,5 @@ sed -e '/^[^#]/!d
s/[ ][ ]*/ /g s/[ ][ ]*/ /g
s/^[^ ][^ ]* [^ ][^ ]* [^ ][^ ]*$/& 0/ s/^[^ ][^ ]* [^ ][^ ]* [^ ][^ ]*$/& 0/
s/^[^ ][^ ]* [^ ][^ ]* [^ ][^ ]* \([^ ][^ ]*\)/ \1,/ s/^[^ ][^ ]* [^ ][^ ]* [^ ][^ ]* \([^ ][^ ]*\)/ \1,/
' unary_op binary_op ' "$unary_op" "$binary_op"
echo '};' echo '};'

View 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);

View file

@ -8,7 +8,9 @@
*/ */
#include "bltin.h" #include "bltin.h"
#include "myregexp.h"
#include <stdlib.h>
#define RE_END 0 /* end of regular expression */ #define RE_END 0 /* end of regular expression */
#define RE_LITERAL 1 /* normal character follows */ #define RE_LITERAL 1 /* normal character follows */
@ -27,7 +29,7 @@
char *match_begin[10]; char *match_begin[10];
short match_length[10]; short match_length[10];
short number_parens; short number_parens;
static int match(); static int match(char *pattern, char *string);
@ -48,7 +50,6 @@ re_compile(pattern)
char stack[10]; char stack[10];
int paren_num; int paren_num;
int i; int i;
char *malloc();
p = pattern; p = pattern;
if (*p == '^') if (*p == '^')
@ -176,6 +177,7 @@ out:
int
re_match(pattern, string) re_match(pattern, string)
char *pattern; char *pattern;
char *string; char *string;
@ -246,7 +248,7 @@ ccl:
p++; p++;
} }
p++; p++;
if (found == negate || c == 0) if (found == negate)
goto bad; goto bad;
break; break;
case RE_LP: case RE_LP:

View file

@ -16,9 +16,8 @@ ISFIFO -p 12 OP_FILE
ISSETUID -u 12 OP_FILE ISSETUID -u 12 OP_FILE
ISSETGID -g 12 OP_FILE ISSETGID -g 12 OP_FILE
ISSTICKY -k 12 OP_FILE ISSTICKY -k 12 OP_FILE
ISSLINK -h 12 OP_FILE
ISSIZE -s 12 OP_FILE ISSIZE -s 12 OP_FILE
ISLINK1 -h 12 OP_LFILE
ISLINK2 -L 12 OP_LFILE
ISTTY -t 12 OP_INT ISTTY -t 12 OP_INT
NULSTR -z 12 OP_STRING NULSTR -z 12 OP_STRING
STRLEN -n 12 OP_STRING STRLEN -n 12 OP_STRING

View file

@ -1,3 +0,0 @@
#!/bin/sh
make clean
make && make install

21
commands/ash/builtins.table → commands/ash/builtins Executable file → Normal file
View file

@ -1,7 +1,7 @@
#!/bin/sh - #!/bin/sh -
# #
# Copyright (c) 1991 The Regents of the University of California. # Copyright (c) 1991, 1993
# All rights reserved. # The Regents of the University of California. All rights reserved.
# #
# This code is derived from software contributed to Berkeley by # This code is derived from software contributed to Berkeley by
# Kenneth Almquist. # Kenneth Almquist.
@ -34,19 +34,21 @@
# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF # OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
# SUCH DAMAGE. # 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 # 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 # 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 # 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 # 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. # come first.
# #
# Copyright (C) 1989 by Kenneth Almquist. 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 # This file is part of ash, which is distributed under the terms specified
# by the Ash General Public License. See the file named LICENSE. # by the Ash General Public License. See the file named LICENSE.
#
# NOTE: bltincmd must come first!
bltincmd command bltincmd command
#alloccmd alloc #alloccmd alloc
@ -59,17 +61,19 @@ echocmd echo
evalcmd eval evalcmd eval
execcmd exec execcmd exec
exitcmd exit exitcmd exit
expcmd exp let
exportcmd export readonly exportcmd export readonly
exprcmd expr test [ #exprcmd expr test [
histcmd fc
fgcmd -j fg fgcmd -j fg
getoptscmd getopts getoptscmd getopts
hashcmd hash hashcmd hash
jobidcmd jobid jobidcmd jobid
jobscmd jobs jobscmd jobs
#lccmd lc
#linecmd line #linecmd line
localcmd local localcmd local
#nlechocmd nlecho #nlechocmd nlecho
printfcmd printf
pwdcmd pwd pwdcmd pwd
readcmd read readcmd read
returncmd return returncmd return
@ -77,7 +81,10 @@ setcmd set
setvarcmd setvar setvarcmd setvar
shiftcmd shift shiftcmd shift
trapcmd trap trapcmd trap
truecmd : true false truecmd : true
umaskcmd umask umaskcmd umask
unaliascmd unalias
unsetcmd unset unsetcmd unset
waitcmd wait waitcmd wait
#foocmd foo
aliascmd alias

94
commands/ash/builtins.def Normal file
View 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 $

View file

@ -1,6 +1,6 @@
/*- /*-
* Copyright (c) 1991 The Regents of the University of California. * Copyright (c) 1991, 1993
* All rights reserved. * The Regents of the University of California. All rights reserved.
* *
* This code is derived from software contributed to Berkeley by * This code is derived from software contributed to Berkeley by
* Kenneth Almquist. * Kenneth Almquist.
@ -13,10 +13,6 @@
* 2. Redistributions in binary form must reproduce the above copyright * 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the * notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution. * 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 * 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 * may be used to endorse or promote products derived from this software
* without specific prior written permission. * without specific prior written permission.
@ -35,8 +31,22 @@
*/ */
#ifndef lint #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 */ #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. * The cd and pwd commands.
@ -50,115 +60,124 @@ static char sccsid[] = "@(#)cd.c 5.2 (Berkeley) 3/13/91";
#include "output.h" #include "output.h"
#include "memalloc.h" #include "memalloc.h"
#include "error.h" #include "error.h"
#include "exec.h"
#include "redir.h"
#include "mystring.h" #include "mystring.h"
#include <sys/types.h> #include "builtins.h"
#include <sys/stat.h> #include "show.h"
#include <errno.h> #include "cd.h"
STATIC int cdlogical(char *);
#ifdef __STDC__ STATIC int cdphysical(char *);
STATIC int docd(char *, int, int); STATIC int docd(char *, int, int);
STATIC void updatepwd(char *);
STATIC void getpwd(void);
STATIC char *getcomponent(void); STATIC char *getcomponent(void);
#else STATIC int updatepwd(char *);
STATIC int docd();
STATIC void updatepwd();
STATIC void getpwd();
STATIC char *getcomponent();
#endif
STATIC char *curdir = NULL; /* current working directory */
char *curdir; /* current working directory */ STATIC char *prevdir; /* previous working directory */
STATIC char *cdcomppath; STATIC char *cdcomppath;
#if UDIR || TILDE
extern int didudir; /* set if /u/logname or ~logname expanded */
#endif
int int
cdcmd(argc, argv) char **argv; { cdcmd(int argc, char **argv)
{
char *dest; char *dest;
char *path; char *path;
char *p; char *p;
struct stat statb; struct stat statb;
char *padvance(); int ch, phys, print = 0;
int tohome= 0;
nextopt(nullstr); optreset = 1; optind = 1; opterr = 0; /* initialize getopt */
if ((dest = *argptr) == NULL) { phys = Pflag;
if ((dest = bltinlookup("HOME", 1)) == NULL) 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"); error("HOME not set");
tohome = 1; 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) if (*dest == '/' || (path = bltinlookup("CDPATH", 1)) == NULL)
path = nullstr; path = nullstr;
while ((p = padvance(&path, dest)) != NULL) { while ((p = padvance(&path, dest)) != NULL) {
if (stat(p, &statb) >= 0 if (stat(p, &statb) >= 0 && S_ISDIR(statb.st_mode)) {
&& (statb.st_mode & S_IFMT) == S_IFDIR if (!print) {
&& docd(p, strcmp(p, dest), tohome) >= 0) /*
* XXX - rethink
*/
if (p[0] == '.' && p[1] == '/' && p[2] != '\0')
p += 2;
print = strcmp(p, dest);
}
if (docd(p, print, phys) >= 0)
return 0; return 0;
} }
}
error("can't cd to %s", dest); error("can't cd to %s", dest);
/*NOTREACHED*/
return 0;
} }
/* /*
* Actually do the chdir. If the name refers to symbolic links, we * Actually change the directory. In an interactive shell, print the
* compute the actual directory name before doing the cd. In an * directory name if "print" is nonzero.
* 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.)
*/ */
#if SYMLINKS == 0
STATIC int STATIC int
docd(dest, print, tohome) docd(char *dest, int print, int phys)
char *dest;
{ {
#if UDIR || TILDE
if (didudir) TRACE(("docd(\"%s\", %d, %d) called\n", dest, print, phys));
print = 1;
#endif /* If logical cd fails, fall back to physical. */
INTOFF; if ((phys || cdlogical(dest) < 0) && cdphysical(dest) < 0)
if (chdir(dest) < 0) { return (-1);
INTON;
return -1; if (print && iflag && curdir)
} out1fmt("%s\n", curdir);
updatepwd(dest);
INTON;
if (print && iflag)
out1fmt("%s\n", stackblock());
return 0; return 0;
} }
#else
STATIC int STATIC int
docd(dest, print, tohome) cdlogical(char *dest)
char *dest;
{ {
register char *p; char *p;
register char *q; char *q;
char *symlink;
char *component; char *component;
struct stat statb; struct stat statb;
int first; int first;
int i; int badstat;
TRACE(("docd(\"%s\", %d, %d) called\n", dest, print, tohome)); /*
#if UDIR || TILDE * Check each component of the path. If we find a symlink or
if (didudir) * something we can't stat, clear curdir to force a getcwd()
print = 1; * next time we get the value of the current directory.
#endif */
badstat = 0;
top: cdcomppath = stalloc(strlen(dest) + 1);
cdcomppath = dest; scopy(dest, cdcomppath);
STARTSTACKSTR(p); STARTSTACKSTR(p);
if (*dest == '/') { if (*dest == '/') {
STPUTC('/', p); STPUTC('/', p);
@ -166,7 +185,7 @@ top:
} }
first = 1; first = 1;
while ((q = getcomponent()) != NULL) { while ((q = getcomponent()) != NULL) {
if (q[0] == '\0' || q[0] == '.' && q[1] == '\0') if (q[0] == '\0' || (q[0] == '.' && q[1] == '\0'))
continue; continue;
if (! first) if (! first)
STPUTC('/', p); STPUTC('/', p);
@ -177,71 +196,42 @@ top:
if (equal(component, "..")) if (equal(component, ".."))
continue; continue;
STACKSTRNUL(p); STACKSTRNUL(p);
if (lstat(stackblock(), &statb) < 0) if (lstat(stackblock(), &statb) < 0) {
error("lstat %s failed", stackblock()); badstat = 1;
if ((statb.st_mode & S_IFMT) != S_IFLNK) break;
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 (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; INTOFF;
/* The empty string is not a legal argument to chdir on a POSIX 1003.1 if (updatepwd(badstat ? NULL : dest) < 0 || chdir(curdir) < 0) {
* system. */
if (p[0] != '\0' && chdir(p) < 0) {
INTON; INTON;
return -1; return (-1);
} }
updatepwd(p);
INTON; INTON;
if (print && !tohome && iflag) return (0);
out1fmt("%s\n", p);
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. * Get the next component of the path name pointed to by cdcomppath.
* This routine overwrites the string pointed to by cdcomppath. * This routine overwrites the string pointed to by cdcomppath.
*/ */
STATIC char * STATIC char *
getcomponent() { getcomponent(void)
register char *p; {
char *p;
char *start; char *start;
if ((p = cdcomppath) == NULL) if ((p = cdcomppath) == NULL)
@ -259,29 +249,43 @@ getcomponent() {
} }
/* /*
* Update curdir (the name of the current directory) in response to a * 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 * cd command. We also call hashcd to let the routines in exec.c know
* that the current directory has changed. * that the current directory has changed.
*/ */
STATIC int
void hashcd(); updatepwd(char *dir)
STATIC void
updatepwd(dir)
char *dir;
{ {
char *new; char *new;
char *p; char *p;
hashcd(); /* update command hash table */ 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); cdcomppath = stalloc(strlen(dir) + 1);
scopy(dir, cdcomppath); scopy(dir, cdcomppath);
STARTSTACKSTR(new); STARTSTACKSTR(new);
if (*dir != '/') { if (*dir != '/') {
if (curdir == NULL)
return;
p = curdir; p = curdir;
while (*p) while (*p)
STPUTC(*p++, new); STPUTC(*p++, new);
@ -300,73 +304,87 @@ updatepwd(dir)
if (new == stackblock()) if (new == stackblock())
STPUTC('/', new); STPUTC('/', new);
STACKSTRNUL(new); STACKSTRNUL(new);
if (curdir) INTOFF;
ckfree(curdir); if (prevdir)
ckfree(prevdir);
prevdir = curdir;
curdir = savestr(stackblock()); curdir = savestr(stackblock());
setvar("PWD", curdir, VEXPORT);
setvar("OLDPWD", prevdir, VEXPORT);
INTON;
return (0);
} }
int int
pwdcmd(argc, argv) char **argv; { pwdcmd(int argc, char **argv)
getpwd(); {
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); out1str(curdir);
out1c('\n'); out1c('\n');
} else {
if (getcwd(buf, sizeof(buf)) == NULL)
error(".: %s", strerror(errno));
out1str(buf);
out1c('\n');
}
return 0; return 0;
} }
/* /*
* Run /bin/pwd to find out what the current directory is. We suppress * Find out what the current directory is. If we already know the current
* 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
* directory, this routine returns immediately. * directory, this routine returns immediately.
*/ */
char *
#define MAXPWD 256 getpwd(void)
{
STATIC void char buf[PATH_MAX];
getpwd() {
char buf[MAXPWD];
char *p;
int i;
int status;
struct job *jp;
int pip[2];
if (curdir) if (curdir)
return; return curdir;
INTOFF; if (getcwd(buf, sizeof(buf)) == NULL) {
if (pipe(pip) < 0) char *pwd = getenv("PWD");
error("Pipe call failed"); struct stat stdot, stpwd;
jp = makejob((union node *)NULL, 1);
if (forkshell(jp, (union node *)NULL, FORK_NOJOB) == 0) { if (pwd && *pwd == '/' && stat(".", &stdot) != -1 &&
close(pip[0]); stat(pwd, &stpwd) != -1 &&
if (pip[1] != 1) { stdot.st_dev == stpwd.st_dev &&
close(1); stdot.st_ino == stpwd.st_ino) {
copyfd(pip[1], 1); curdir = savestr(pwd);
close(pip[1]); return curdir;
} }
execl("/bin/pwd", "pwd", (char *)0); return NULL;
error("Cannot exec /bin/pwd");
} }
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); 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
View 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
View 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
View 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 $
*/

View file

@ -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
View 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
View 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

View file

@ -1,6 +1,6 @@
/*- /*-
* Copyright (c) 1991 The Regents of the University of California. * Copyright (c) 1991, 1993
* All rights reserved. * The Regents of the University of California. All rights reserved.
* *
* This code is derived from software contributed to Berkeley by * This code is derived from software contributed to Berkeley by
* Kenneth Almquist. * Kenneth Almquist.
@ -13,10 +13,6 @@
* 2. Redistributions in binary form must reproduce the above copyright * 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the * notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution. * 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 * 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 * may be used to endorse or promote products derived from this software
* without specific prior written permission. * without specific prior written permission.
@ -35,8 +31,14 @@
*/ */
#ifndef lint #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 */ #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. * Errors and exceptions.
@ -47,14 +49,14 @@ static char sccsid[] = "@(#)error.c 5.1 (Berkeley) 3/7/91";
#include "options.h" #include "options.h"
#include "output.h" #include "output.h"
#include "error.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> #include <signal.h>
#ifdef __STDC__ #include <stdlib.h>
#include "stdarg.h" #include <unistd.h>
#else
#include <varargs.h>
#endif
#include <errno.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; struct jmploc *handler;
int exception; volatile sig_atomic_t exception;
volatile int suppressint; volatile sig_atomic_t suppressint;
volatile int intpending; volatile sig_atomic_t intpending;
char *commandname; 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 * 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 * just do a longjmp to the exception handler. The type of exception is
@ -75,7 +79,8 @@ char *commandname;
*/ */
void void
exraise(e) { exraise(int e)
{
if (handler == NULL) if (handler == NULL)
abort(); abort();
exception = e; exception = e;
@ -87,69 +92,63 @@ exraise(e) {
* Called from trap.c when a SIGINT is received. (If the user specifies * 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 * that SIGINT is to be trapped or ignored using the trap builtin, then
* this routine is not called.) Suppressint is nonzero when interrupts * this routine is not called.) Suppressint is nonzero when interrupts
* are held using the INTOFF macro. The call to _exit is necessary because * are held using the INTOFF macro. If SIGINTs are not suppressed and
* there is a short period after a fork before the signal handlers are * the shell is not a root shell, then we want to be terminated if we
* set to the appropriate value for the child. (The test for iflag is * get here, as if we were terminated directly by a SIGINT. Arrange for
* just defensive programming.) * this here.
*/ */
void void
onint() { onint(void)
if (suppressint) { {
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++; intpending++;
return; return;
} }
intpending = 0; intpending = 0;
#ifdef BSD sigemptyset(&sigset);
sigsetmask(0); 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 #endif
if (rootshell && iflag) if (rootshell && iflag)
exraise(EXINT); exraise(EXINT);
else else {
_exit(128 + SIGINT); signal(SIGINT, SIG_DFL);
kill(getpid(), SIGINT);
} }
void
error2(a, b)
char *a, *b;
{
error("%s: %s", a, b);
} }
/* /*
* 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 * is not NULL then error prints an error message using printf style
* formatting. It then raises the error exception. * formatting. It then raises the error exception.
*/ */
static void
#ifdef __STDC__ exverror(int cond, const char *msg, va_list ap)
void
error(char *msg, ...) {
#else
void
error(va_alist)
va_dcl
{ {
char *msg;
#endif
va_list ap;
CLEAR_PENDING_INT; CLEAR_PENDING_INT;
INTOFF; INTOFF;
#ifdef __STDC__
va_start(ap, msg);
#else
va_start(ap);
msg = va_arg(ap, char *);
#endif
#if DEBUG #if DEBUG
if (msg) if (msg)
TRACE(("error(\"%s\") pid=%d\n", msg, getpid())); TRACE(("exverror(%d, \"%s\") pid=%d\n", cond, msg, getpid()));
else else
TRACE(("error(NULL) pid=%d\n", getpid())); TRACE(("exverror(%d, NULL) pid=%d\n", cond, getpid()));
#endif #endif
if (msg) { if (msg) {
if (commandname) if (commandname)
@ -157,96 +156,30 @@ error(va_alist)
doformat(&errout, msg, ap); doformat(&errout, msg, ap);
out2c('\n'); out2c('\n');
} }
va_end(ap);
flushall(); flushall();
exraise(EXERROR); exraise(cond);
} }
#ifdef notdef /* These strange error messages only confuse. -- kjb */ void
/* error(const char *msg, ...)
* Table of error messages. {
*/ va_list ap;
va_start(ap, msg);
struct errname { exverror(EXERROR, msg, ap);
short errcode; /* error number */ va_end(ap);
short action; /* operation which encountered the error */ }
char *msg; /* text describing the error */
};
#define ALL (E_OPEN|E_CREAT|E_EXEC) void
exerror(int cond, const char *msg, ...)
STATIC const struct errname errormsg[] = { {
EINTR, ALL, "interrupted", va_list ap;
EACCES, ALL, "permission denied", va_start(ap, msg);
EIO, ALL, "I/O error", exverror(cond, msg, ap);
ENOENT, E_OPEN, "no such file", va_end(ap);
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 * $PchId: error.c,v 1.5 2006/04/10 14:36:23 philip Exp $
* 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;
}
#endif

View file

@ -1,6 +1,6 @@
/*- /*-
* Copyright (c) 1991 The Regents of the University of California. * Copyright (c) 1991, 1993
* All rights reserved. * The Regents of the University of California. All rights reserved.
* *
* This code is derived from software contributed to Berkeley by * This code is derived from software contributed to Berkeley by
* Kenneth Almquist. * Kenneth Almquist.
@ -13,10 +13,6 @@
* 2. Redistributions in binary form must reproduce the above copyright * 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the * notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution. * 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 * 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 * may be used to endorse or promote products derived from this software
* without specific prior written permission. * without specific prior written permission.
@ -33,41 +29,35 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE. * 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 * 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 locations. The global variable handler contains the location to
* jump to when an exception occurs, and the global variable exception * 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 * 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 * to an inner scope, set handler to point to a jmploc structure for the
* inner scope, and restore handler on exit from the scope. * inner scope, and restore handler on exit from the scope.
*/ */
#include <setjmp.h> #include <setjmp.h>
#include <signal.h>
struct jmploc { struct jmploc {
jmp_buf loc; jmp_buf loc;
}; };
extern struct jmploc *handler; extern struct jmploc *handler;
extern int exception; extern volatile sig_atomic_t exception;
/* exceptions */ /* exceptions */
#define EXINT 0 /* SIGINT received */ #define EXINT 0 /* SIGINT received */
#define EXERROR 1 /* a generic error */ #define EXERROR 1 /* a generic error */
#define EXSHELLPROC 2 /* execute a shell procedure */ #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. :-)) * more fun than worrying about efficiency and portability. :-))
*/ */
extern volatile int suppressint; extern volatile sig_atomic_t suppressint;
extern volatile int intpending; extern volatile sig_atomic_t intpending;
extern char *commandname; /* name of command--printed on error */
#define INTOFF suppressint++ #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 FORCEINTON {suppressint = 0; if (intpending) onint();}
#define CLEAR_PENDING_INT intpending = 0 #define CLEAR_PENDING_INT intpending = 0
#define int_pending() intpending #define int_pending() intpending
#ifdef __STDC__ #define __printf0like(a,b)
void exraise(int); void exraise(int);
void onint(void); void onint(void);
void error2(char *, char *); void error(const char *, ...) __printf0like(1, 2);
void error(char *, ...); void exerror(int, const char *, ...) __printf0like(2, 3);
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)
/* /*
@ -111,6 +90,12 @@ char *errmsg();
*/ */
#ifdef BSD #ifdef BSD
#ifndef __minix
#define setjmp(jmploc) _setjmp(jmploc) #define setjmp(jmploc) _setjmp(jmploc)
#define longjmp(jmploc, val) _longjmp(jmploc, val) #define longjmp(jmploc, val) _longjmp(jmploc, val)
#endif #endif
#endif
/*
* $PchId: error.h,v 1.5 2006/04/10 14:36:43 philip Exp $
*/

View file

@ -1,6 +1,6 @@
/*- /*-
* Copyright (c) 1991 The Regents of the University of California. * Copyright (c) 1993
* All rights reserved. * The Regents of the University of California. All rights reserved.
* *
* This code is derived from software contributed to Berkeley by * This code is derived from software contributed to Berkeley by
* Kenneth Almquist. * Kenneth Almquist.
@ -13,10 +13,6 @@
* 2. Redistributions in binary form must reproduce the above copyright * 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the * notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution. * 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 * 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 * may be used to endorse or promote products derived from this software
* without specific prior written permission. * without specific prior written permission.
@ -35,8 +31,23 @@
*/ */
#ifndef lint #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 */ #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. * Evaluate a command.
@ -59,22 +70,21 @@ static char sccsid[] = "@(#)eval.c 5.3 (Berkeley) 4/12/91";
#include "var.h" #include "var.h"
#include "memalloc.h" #include "memalloc.h"
#include "error.h" #include "error.h"
#include "show.h"
#include "mystring.h" #include "mystring.h"
#include <sys/types.h> #if !defined(NO_HISTORY) && !defined(EDITLINE)
#include <signal.h> #include "myhistedit.h"
#endif
#ifndef _PATH_STDPATH
#define _PATH_STDPATH "/usr/bin:/bin:/usr/sbin:/sbin:"
#endif
/* flags in argument to evaltree */ /* flags in argument to evaltree */
#define EV_EXIT 01 /* exit after evaluating tree */ #define EV_EXIT 01 /* exit after evaluating tree */
#define EV_TESTED 02 /* exit status is checked; ignore -e flag */ #define EV_TESTED 02 /* exit status is checked; ignore -e flag */
#define EV_BACKCMD 04 /* command executing within back quotes */ #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 */ MKINIT int evalskip; /* set if we are skipping commands */
STATIC int skipcount; /* number of levels to skip */ STATIC int skipcount; /* number of levels to skip */
MKINIT int loopnest; /* current loop nesting level */ MKINIT int loopnest; /* current loop nesting level */
@ -87,7 +97,6 @@ int exitstatus; /* exit status of last command */
int oexitstatus; /* saved exit status */ int oexitstatus; /* saved exit status */
#ifdef __STDC__
STATIC void evalloop(union node *); STATIC void evalloop(union node *);
STATIC void evalfor(union node *); STATIC void evalfor(union node *);
STATIC void evalcase(union node *, int); STATIC void evalcase(union node *, int);
@ -96,17 +105,6 @@ STATIC void expredir(union node *);
STATIC void evalpipe(union node *); STATIC void evalpipe(union node *);
STATIC void evalcommand(union node *, int, struct backcmd *); STATIC void evalcommand(union node *, int, struct backcmd *);
STATIC void prehash(union node *); 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) int
char **argv; evalcmd(int argc, char **argv)
{ {
char *p; char *p;
char *concat; char *concat;
@ -166,8 +164,7 @@ evalcmd(argc, argv)
*/ */
void void
evalstring(s) evalstring(char *s)
char *s;
{ {
union node *n; union node *n;
struct stackmark smark; struct stackmark smark;
@ -190,14 +187,17 @@ evalstring(s)
*/ */
void void
evaltree(n, flags) evaltree(union node *n, int flags)
union node *n;
{ {
if (n == NULL) { if (n == NULL) {
TRACE(("evaltree(NULL) called\n")); 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) { switch (n->type) {
case NSEMI: case NSEMI:
evaltree(n->nbinary.ch1, 0); evaltree(n->nbinary.ch1, 0);
@ -207,8 +207,9 @@ evaltree(n, flags)
break; break;
case NAND: case NAND:
evaltree(n->nbinary.ch1, EV_TESTED); evaltree(n->nbinary.ch1, EV_TESTED);
if (evalskip || exitstatus != 0) if (evalskip || exitstatus != 0) {
goto out; goto out;
}
evaltree(n->nbinary.ch2, flags); evaltree(n->nbinary.ch2, flags);
break; break;
case NOR: case NOR:
@ -230,19 +231,15 @@ evaltree(n, flags)
evalsubshell(n, flags); evalsubshell(n, flags);
break; break;
case NIF: { case NIF: {
int status = 0;
evaltree(n->nif.test, EV_TESTED); evaltree(n->nif.test, EV_TESTED);
if (evalskip) if (evalskip)
goto out; goto out;
if (exitstatus == 0) { if (exitstatus == 0)
evaltree(n->nif.ifpart, flags); evaltree(n->nif.ifpart, flags);
status = exitstatus; else if (n->nif.elsepart)
} else if (n->nif.elsepart) {
evaltree(n->nif.elsepart, flags); evaltree(n->nif.elsepart, flags);
status = exitstatus; else
} exitstatus = 0;
exitstatus = status;
break; break;
} }
case NWHILE: case NWHILE:
@ -259,6 +256,11 @@ evaltree(n, flags)
defun(n->narg.text, n->narg.next); defun(n->narg.text, n->narg.next);
exitstatus = 0; exitstatus = 0;
break; break;
case NNOT:
evaltree(n->nnot.com, EV_TESTED);
exitstatus = !exitstatus;
break;
case NPIPE: case NPIPE:
evalpipe(n); evalpipe(n);
break; break;
@ -275,15 +277,13 @@ out:
dotrap(); dotrap();
if ((flags & EV_EXIT) || (eflag && exitstatus if ((flags & EV_EXIT) || (eflag && exitstatus
&& !(flags & EV_TESTED) && (n->type == NCMD || && !(flags & EV_TESTED) && (n->type == NCMD ||
n->type == NSUBSHELL))) { n->type == NSUBSHELL)))
exitshell(exitstatus); exitshell(exitstatus);
} }
}
STATIC void STATIC void
evalloop(n) evalloop(union node *n)
union node *n;
{ {
int status; int status;
@ -319,8 +319,7 @@ skipping: if (evalskip == SKIPCONT && --skipcount <= 0) {
STATIC void STATIC void
evalfor(n) evalfor(union node *n)
union node *n;
{ {
struct arglist arglist; struct arglist arglist;
union node *argp; union node *argp;
@ -331,7 +330,7 @@ evalfor(n)
arglist.lastp = &arglist.list; arglist.lastp = &arglist.list;
for (argp = n->nfor.args ; argp ; argp = argp->narg.next) { for (argp = n->nfor.args ; argp ; argp = argp->narg.next) {
oexitstatus = exitstatus; oexitstatus = exitstatus;
expandarg(argp, &arglist, 1); expandarg(argp, &arglist, EXP_FULL | EXP_TILDE);
if (evalskip) if (evalskip)
goto out; goto out;
} }
@ -360,8 +359,7 @@ out:
STATIC void STATIC void
evalcase(n, flags) evalcase(union node *n, int flags)
union node *n;
{ {
union node *cp; union node *cp;
union node *patp; union node *patp;
@ -371,7 +369,7 @@ evalcase(n, flags)
setstackmark(&smark); setstackmark(&smark);
arglist.lastp = &arglist.list; arglist.lastp = &arglist.list;
oexitstatus = exitstatus; oexitstatus = exitstatus;
expandarg(n->ncase.expr, &arglist, 0); expandarg(n->ncase.expr, &arglist, EXP_TILDE);
for (cp = n->ncase.cases ; cp && evalskip == 0 ; cp = cp->nclist.next) { for (cp = n->ncase.cases ; cp && evalskip == 0 ; cp = cp->nclist.next) {
for (patp = cp->nclist.pattern ; patp ; patp = patp->narg.next) { for (patp = cp->nclist.pattern ; patp ; patp = patp->narg.next) {
if (casematch(patp, arglist.list->text)) { if (casematch(patp, arglist.list->text)) {
@ -393,8 +391,7 @@ out:
*/ */
STATIC void STATIC void
evalsubshell(n, flags) evalsubshell(union node *n, int flags)
union node *n;
{ {
struct job *jp; struct job *jp;
int backgnd = (n->type == NBACKGND); int backgnd = (n->type == NBACKGND);
@ -409,7 +406,7 @@ evalsubshell(n, flags)
} }
if (! backgnd) { if (! backgnd) {
INTOFF; INTOFF;
exitstatus = waitforjob(jp); exitstatus = waitforjob(jp, (int *)NULL);
INTON; INTON;
} }
} }
@ -421,20 +418,30 @@ evalsubshell(n, flags)
*/ */
STATIC void STATIC void
expredir(n) expredir(union node *n)
union node *n;
{ {
register union node *redir; union node *redir;
for (redir = n ; redir ; redir = redir->nfile.next) { for (redir = n ; redir ; redir = redir->nfile.next) {
oexitstatus = exitstatus;
if (redir->type == NFROM
|| redir->type == NTO
|| redir->type == NAPPEND) {
struct arglist fn; struct arglist fn;
fn.lastp = &fn.list; fn.lastp = &fn.list;
expandarg(redir->nfile.fname, &fn, 0); oexitstatus = exitstatus;
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; 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,8 +456,7 @@ expredir(n)
*/ */
STATIC void STATIC void
evalpipe(n) evalpipe(union node *n)
union node *n;
{ {
struct job *jp; struct job *jp;
struct nodelist *lp; struct nodelist *lp;
@ -458,7 +464,7 @@ evalpipe(n)
int prevfd; int prevfd;
int pip[2]; int pip[2];
TRACE(("evalpipe(0x%x) called\n", (int)n)); TRACE(("evalpipe(0x%lx) called\n", (long)n));
pipelen = 0; pipelen = 0;
for (lp = n->npipe.cmdlist ; lp ; lp = lp->next) for (lp = n->npipe.cmdlist ; lp ; lp = lp->next)
pipelen++; pipelen++;
@ -471,21 +477,20 @@ evalpipe(n)
if (lp->next) { if (lp->next) {
if (pipe(pip) < 0) { if (pipe(pip) < 0) {
close(prevfd); close(prevfd);
error("Pipe call failed"); error("Pipe call failed: %s", strerror(errno));
} }
} }
if (forkshell(jp, lp->n, n->npipe.backgnd) == 0) { if (forkshell(jp, lp->n, n->npipe.backgnd) == 0) {
INTON; INTON;
if (prevfd > 0) { if (prevfd > 0) {
close(0); dup2(prevfd, 0);
copyfd(prevfd, 0);
close(prevfd); close(prevfd);
} }
if (pip[1] >= 0) { if (pip[1] >= 0) {
if (!(prevfd >= 0 && pip[0] == 0))
close(pip[0]); close(pip[0]);
if (pip[1] != 1) { if (pip[1] != 1) {
close(1); dup2(pip[1], 1);
copyfd(pip[1], 1);
close(pip[1]); close(pip[1]);
} }
} }
@ -499,7 +504,7 @@ evalpipe(n)
INTON; INTON;
if (n->npipe.backgnd == 0) { if (n->npipe.backgnd == 0) {
INTOFF; INTOFF;
exitstatus = waitforjob(jp); exitstatus = waitforjob(jp, (int *)NULL);
TRACE(("evalpipe: job done exit status %d\n", exitstatus)); TRACE(("evalpipe: job done exit status %d\n", exitstatus));
INTON; INTON;
} }
@ -515,9 +520,7 @@ evalpipe(n)
*/ */
void void
evalbackcmd(n, result) evalbackcmd(union node *n, struct backcmd *result)
union node *n;
struct backcmd *result;
{ {
int pip[2]; int pip[2];
struct job *jp; struct job *jp;
@ -529,21 +532,22 @@ evalbackcmd(n, result)
result->nleft = 0; result->nleft = 0;
result->jp = NULL; result->jp = NULL;
if (n == NULL) { if (n == NULL) {
/* `` */ exitstatus = 0;
} else goto out;
}
if (n->type == NCMD) { if (n->type == NCMD) {
exitstatus = oexitstatus; exitstatus = oexitstatus;
evalcommand(n, EV_BACKCMD, result); evalcommand(n, EV_BACKCMD, result);
} else { } else {
exitstatus = 0;
if (pipe(pip) < 0) if (pipe(pip) < 0)
error("Pipe call failed"); error("Pipe call failed: %s", strerror(errno));
jp = makejob(n, 1); jp = makejob(n, 1);
if (forkshell(jp, n, FORK_NOJOB) == 0) { if (forkshell(jp, n, FORK_NOJOB) == 0) {
FORCEINTON; FORCEINTON;
close(pip[0]); close(pip[0]);
if (pip[1] != 1) { if (pip[1] != 1) {
close(1); dup2(pip[1], 1);
copyfd(pip[1], 1);
close(pip[1]); close(pip[1]);
} }
evaltree(n, EV_EXIT); evaltree(n, EV_EXIT);
@ -552,8 +556,9 @@ evalbackcmd(n, result)
result->fd = pip[0]; result->fd = pip[0];
result->jp = jp; result->jp = jp;
} }
out:
popstackmark(&smark); 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)); result->fd, result->buf, result->nleft, result->jp));
} }
@ -564,9 +569,7 @@ evalbackcmd(n, result)
*/ */
STATIC void STATIC void
evalcommand(cmd, flags, backcmd) evalcommand(union node *cmd, int flags, struct backcmd *backcmd)
union node *cmd;
struct backcmd *backcmd;
{ {
struct stackmark smark; struct stackmark smark;
union node *argp; union node *argp;
@ -577,7 +580,6 @@ evalcommand(cmd, flags, backcmd)
char **envp; char **envp;
int varflag; int varflag;
struct strlist *sp; struct strlist *sp;
register char *p;
int mode; int mode;
int pip[2]; int pip[2];
struct cmdentry cmdentry; struct cmdentry cmdentry;
@ -589,27 +591,38 @@ evalcommand(cmd, flags, backcmd)
struct localvar *volatile savelocalvars; struct localvar *volatile savelocalvars;
volatile int e; volatile int e;
char *lastarg; 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. */ /* 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); setstackmark(&smark);
arglist.lastp = &arglist.list; arglist.lastp = &arglist.list;
varlist.lastp = &varlist.list; varlist.lastp = &varlist.list;
varflag = 1; varflag = 1;
do_clearcmdentry = 0;
oexitstatus = exitstatus; oexitstatus = exitstatus;
exitstatus = 0; exitstatus = 0;
for (argp = cmd->ncmd.args ; argp ; argp = argp->narg.next) { for (argp = cmd->ncmd.args ; argp ; argp = argp->narg.next) {
p = argp->narg.text; char *p = argp->narg.text;
if (varflag && is_name(*p)) { if (varflag && is_name(*p)) {
do { do {
p++; p++;
} while (is_in_name(*p)); } while (is_in_name(*p));
if (*p == '=') { if (*p == '=') {
expandarg(argp, &varlist, 0); expandarg(argp, &varlist, EXP_VARTILDE);
continue; continue;
} }
} }
expandarg(argp, &arglist, 1); expandarg(argp, &arglist, EXP_FULL | EXP_TILDE);
varflag = 0; varflag = 0;
} }
*arglist.lastp = NULL; *arglist.lastp = NULL;
@ -619,8 +632,11 @@ evalcommand(cmd, flags, backcmd)
for (sp = arglist.list ; sp ; sp = sp->next) for (sp = arglist.list ; sp ; sp = sp->next)
argc++; argc++;
argv = stalloc(sizeof (char *) * (argc + 1)); 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++ = sp->text;
}
*argv = NULL; *argv = NULL;
lastarg = NULL; lastarg = NULL;
if (iflag && funcnest == 0 && argc > 0) if (iflag && funcnest == 0 && argc > 0)
@ -628,7 +644,7 @@ evalcommand(cmd, flags, backcmd)
argv -= argc; argv -= argc;
/* Print the command if xflag is set. */ /* Print the command if xflag is set. */
if (xflag == 1) { if (xflag) {
outc('+', &errout); outc('+', &errout);
for (sp = varlist.list ; sp ; sp = sp->next) { for (sp = varlist.list ; sp ; sp = sp->next) {
outc(' ', &errout); outc(' ', &errout);
@ -647,11 +663,42 @@ evalcommand(cmd, flags, backcmd)
cmdentry.cmdtype = CMDBUILTIN; cmdentry.cmdtype = CMDBUILTIN;
cmdentry.u.index = BLTINCMD; cmdentry.u.index = BLTINCMD;
} else { } 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 */ if (cmdentry.cmdtype == CMDUNKNOWN) { /* command not found */
exitstatus = 2; exitstatus = 127;
flushout(&errout); flushout(&errout);
popstackmark(&smark);
return; return;
} }
/* implement the bltin builtin here */ /* implement the bltin builtin here */
@ -662,9 +709,8 @@ evalcommand(cmd, flags, backcmd)
break; break;
if ((cmdentry.u.index = find_builtin(*argv)) < 0) { if ((cmdentry.u.index = find_builtin(*argv)) < 0) {
outfmt(&errout, "%s: not found\n", *argv); outfmt(&errout, "%s: not found\n", *argv);
exitstatus = 2; exitstatus = 127;
flushout(&errout); flushout(&errout);
popstackmark(&smark);
return; return;
} }
if (cmdentry.u.index != BLTINCMD) if (cmdentry.u.index != BLTINCMD)
@ -675,17 +721,21 @@ evalcommand(cmd, flags, backcmd)
/* Fork off a child process if necessary. */ /* Fork off a child process if necessary. */
if (cmd->ncmd.backgnd if (cmd->ncmd.backgnd
|| cmdentry.cmdtype == CMDNORMAL && (flags & EV_EXIT) == 0 || (cmdentry.cmdtype == CMDNORMAL
|| (flags & EV_BACKCMD) != 0 && ((flags & EV_EXIT) == 0 || Tflag))
|| ((flags & EV_BACKCMD) != 0
&& (cmdentry.cmdtype != CMDBUILTIN && (cmdentry.cmdtype != CMDBUILTIN
|| cmdentry.u.index == CDCMD
|| cmdentry.u.index == DOTCMD || cmdentry.u.index == DOTCMD
|| cmdentry.u.index == EVALCMD)) { || cmdentry.u.index == EVALCMD))
|| (cmdentry.cmdtype == CMDBUILTIN &&
cmdentry.u.index == COMMANDCMD)) {
jp = makejob(cmd, 1); jp = makejob(cmd, 1);
mode = cmd->ncmd.backgnd; mode = cmd->ncmd.backgnd;
if (flags & EV_BACKCMD) { if (flags & EV_BACKCMD) {
mode = FORK_NOJOB; mode = FORK_NOJOB;
if (pipe(pip) < 0) if (pipe(pip) < 0)
error("Pipe call failed"); error("Pipe call failed: %s", strerror(errno));
} }
if (forkshell(jp, cmd, mode) != 0) if (forkshell(jp, cmd, mode) != 0)
goto parent; /* at end of routine */ goto parent; /* at end of routine */
@ -693,8 +743,7 @@ evalcommand(cmd, flags, backcmd)
FORCEINTON; FORCEINTON;
close(pip[0]); close(pip[0]);
if (pip[1] != 1) { if (pip[1] != 1) {
close(1); dup2(pip[1], 1);
copyfd(pip[1], 1);
close(pip[1]); close(pip[1]);
} }
} }
@ -704,10 +753,13 @@ evalcommand(cmd, flags, backcmd)
/* This is the child process if a fork occurred. */ /* This is the child process if a fork occurred. */
/* Execute the command. */ /* Execute the command. */
if (cmdentry.cmdtype == CMDFUNCTION) { if (cmdentry.cmdtype == CMDFUNCTION) {
#if DEBUG
trputs("Shell function: "); trargs(argv); trputs("Shell function: "); trargs(argv);
#endif
redirect(cmd->ncmd.redirect, REDIR_PUSH); redirect(cmd->ncmd.redirect, REDIR_PUSH);
saveparam = shellparam; saveparam = shellparam;
shellparam.malloc = 0; shellparam.malloc = 0;
shellparam.reset = 1;
shellparam.nparam = argc - 1; shellparam.nparam = argc - 1;
shellparam.p = argv + 1; shellparam.p = argv + 1;
shellparam.optnext = NULL; shellparam.optnext = NULL;
@ -752,7 +804,9 @@ evalcommand(cmd, flags, backcmd)
if (flags & EV_EXIT) if (flags & EV_EXIT)
exitshell(exitstatus); exitshell(exitstatus);
} else if (cmdentry.cmdtype == CMDBUILTIN) { } else if (cmdentry.cmdtype == CMDBUILTIN) {
#if DEBUG
trputs("builtin command: "); trargs(argv); trputs("builtin command: "); trargs(argv);
#endif
mode = (cmdentry.u.index == EXECCMD)? 0 : REDIR_PUSH; mode = (cmdentry.u.index == EXECCMD)? 0 : REDIR_PUSH;
if (flags == EV_BACKCMD) { if (flags == EV_BACKCMD) {
memout.nleft = 0; memout.nleft = 0;
@ -777,6 +831,7 @@ evalcommand(cmd, flags, backcmd)
exitstatus = (*builtinfunc[cmdentry.u.index])(argc, argv); exitstatus = (*builtinfunc[cmdentry.u.index])(argc, argv);
flushall(); flushall();
cmddone: cmddone:
cmdenviron = NULL;
out1 = &output; out1 = &output;
out2 = &errout; out2 = &errout;
freestdout(); freestdout();
@ -788,10 +843,15 @@ cmddone:
} }
handler = savehandler; handler = savehandler;
if (e != -1) { if (e != -1) {
if (e != EXERROR || cmdentry.u.index == BLTINCMD if ((e != EXERROR && e != EXEXEC)
|| cmdentry.u.index == BLTINCMD
|| cmdentry.u.index == DOTCMD || cmdentry.u.index == DOTCMD
|| cmdentry.u.index == EVALCMD || cmdentry.u.index == EVALCMD
|| cmdentry.u.index == EXECCMD) #ifndef NO_HISTORY
|| cmdentry.u.index == HISTCMD
#endif
|| cmdentry.u.index == EXECCMD
|| cmdentry.u.index == COMMANDCMD)
exraise(e); exraise(e);
FORCEINTON; FORCEINTON;
} }
@ -803,19 +863,15 @@ cmddone:
memout.buf = NULL; memout.buf = NULL;
} }
} else { } else {
#if DEBUG
trputs("normal command: "); trargs(argv); trputs("normal command: "); trargs(argv);
#endif
clearredir(); clearredir();
redirect(cmd->ncmd.redirect, 0); 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) for (sp = varlist.list ; sp ; sp = sp->next)
setvareq(sp->text, VEXPORT|VSTACK); setvareq(sp->text, VEXPORT|VSTACK);
envp = environment(); envp = environment();
shellexec(argv, envp, p, cmdentry.u.index); shellexec(argv, envp, pathval(), cmdentry.u.index);
/*NOTREACHED*/ /*NOTREACHED*/
} }
goto out; goto out;
@ -823,8 +879,12 @@ cmddone:
parent: /* parent process gets here (if we forked) */ parent: /* parent process gets here (if we forked) */
if (mode == 0) { /* argument to fork */ if (mode == 0) { /* argument to fork */
INTOFF; INTOFF;
exitstatus = waitforjob(jp); exitstatus = waitforjob(jp, &realstatus);
INTON; INTON;
if (iflag && loopnest > 0 && WIFSIGNALED(realstatus)) {
evalskip = SKIPBREAK;
skipcount = loopnest;
}
} else if (mode == 2) { } else if (mode == 2) {
backcmd->fd = pip[0]; backcmd->fd = pip[0];
close(pip[1]); close(pip[1]);
@ -834,6 +894,8 @@ parent: /* parent process gets here (if we forked) */
out: out:
if (lastarg) if (lastarg)
setvar("_", lastarg, 0); setvar("_", lastarg, 0);
if (do_clearcmdentry)
clearcmdentry(0);
popstackmark(&smark); popstackmark(&smark);
} }
@ -847,13 +909,14 @@ out:
*/ */
STATIC void STATIC void
prehash(n) prehash(union node *n)
union node *n;
{ {
struct cmdentry entry; struct cmdentry entry;
if (n->type == NCMD && goodname(n->ncmd.args->narg.text)) if (n->type == NCMD && n->ncmd.args)
find_command(n->ncmd.args->narg.text, &entry, 0); 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. * specified variables.
*/ */
bltincmd(argc, argv) char **argv; { int
bltincmd(int argc __unused, char **argv __unused)
{
listsetvar(cmdenviron); listsetvar(cmdenviron);
/*
* Preserve exitstatus of a previous possible redirection
* as POSIX mandates
*/
return exitstatus; return exitstatus;
} }
@ -885,12 +954,11 @@ bltincmd(argc, argv) char **argv; {
* in the standard shell so we don't make it one here. * in the standard shell so we don't make it one here.
*/ */
breakcmd(argc, argv) char **argv; { int
int n; 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) if (n > loopnest)
n = loopnest; n = loopnest;
if (n > 0) { if (n > 0) {
@ -900,40 +968,108 @@ breakcmd(argc, argv) char **argv; {
return 0; 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. * The return command.
*/ */
returncmd(argc, argv) char **argv; { int
int ret; returncmd(int argc, char **argv)
{
int ret = argc > 1 ? number(argv[1]) : oexitstatus;
ret = oexitstatus;
if (argc > 1)
ret = number(argv[1]);
if (funcnest) { if (funcnest) {
evalskip = SKIPFUNC; evalskip = SKIPFUNC;
skipcount = 1; skipcount = 1;
} else {
/* skip the rest of the file */
evalskip = SKIPFILE;
skipcount = 1;
} }
return ret; return ret;
} }
truecmd(argc, argv) char **argv; { int
return strcmp(argv[0], "false") == 0 ? 1 : 0; 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) { if (argc > 1) {
struct strlist *sp;
iflag = 0; /* exit on error */ iflag = 0; /* exit on error */
setinteractive(0); mflag = 0;
#if JOBS optschanged();
jflag = 0; for (sp = cmdenviron; sp ; sp = sp->next)
setjobctl(0); setvareq(sp->text, VEXPORT|VSTACK);
#endif
shellexec(argv + 1, environment(), pathval(), 0); shellexec(argv + 1, environment(), pathval(), 0);
} }
return 0; return 0;
} }
/*
* $PchId: eval.c,v 1.7 2006/04/10 14:46:14 philip Exp $
*/

View file

@ -1,6 +1,6 @@
/*- /*-
* Copyright (c) 1991 The Regents of the University of California. * Copyright (c) 1991, 1993
* All rights reserved. * The Regents of the University of California. All rights reserved.
* *
* This code is derived from software contributed to Berkeley by * This code is derived from software contributed to Berkeley by
* Kenneth Almquist. * Kenneth Almquist.
@ -13,10 +13,6 @@
* 2. Redistributions in binary form must reproduce the above copyright * 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the * notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution. * 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 * 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 * may be used to endorse or promote products derived from this software
* without specific prior written permission. * without specific prior written permission.
@ -33,7 +29,8 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE. * 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 */ extern char *commandname; /* currently executing command */
@ -48,18 +45,30 @@ struct backcmd { /* result of evalbackcmd */
struct job *jp; /* job structure for command */ struct job *jp; /* job structure for command */
}; };
int evalcmd(int, char **);
#ifdef __STDC__
void evalstring(char *); void evalstring(char *);
union node; /* BLETCH for ansi C */ union node; /* BLETCH for ansi C */
void evaltree(union node *, int); void evaltree(union node *, int);
void evalbackcmd(union node *, struct backcmd *); void evalbackcmd(union node *, struct backcmd *);
#else int bltincmd(int, char **);
void evalstring(); int breakcmd(int, char **);
void evaltree(); int returncmd(int, char **);
void evalbackcmd(); int falsecmd(int, char **);
#endif int truecmd(int, char **);
int execcmd(int, char **);
int commandcmd(int, char **);
/* in_function returns nonzero if we are currently evaluating a function */ /* in_function returns nonzero if we are currently evaluating a function */
#define in_function() funcnest #define in_function() funcnest
extern int 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 $
*/

View file

@ -1,6 +1,6 @@
/*- /*-
* Copyright (c) 1991 The Regents of the University of California. * Copyright (c) 1991, 1993
* All rights reserved. * The Regents of the University of California. All rights reserved.
* *
* This code is derived from software contributed to Berkeley by * This code is derived from software contributed to Berkeley by
* Kenneth Almquist. * Kenneth Almquist.
@ -13,10 +13,6 @@
* 2. Redistributions in binary form must reproduce the above copyright * 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the * notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution. * 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 * 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 * may be used to endorse or promote products derived from this software
* without specific prior written permission. * without specific prior written permission.
@ -35,8 +31,21 @@
*/ */
#ifndef lint #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 */ #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. * 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 "error.h"
#include "init.h" #include "init.h"
#include "mystring.h" #include "mystring.h"
#include <sys/types.h> #include "show.h"
#include <sys/stat.h> #include "jobs.h"
#include <fcntl.h> #include "alias.h"
#include <errno.h>
#include <limits.h>
#define CMDTABLESIZE 31 /* should be prime */ #define CMDTABLESIZE 31 /* should be prime */
@ -87,23 +94,14 @@ struct tblentry {
STATIC struct tblentry *cmdtable[CMDTABLESIZE]; STATIC struct tblentry *cmdtable[CMDTABLESIZE];
STATIC int builtinloc = -1; /* index in path of %builtin, or -1 */ 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 tryexec(char *, char **, char **);
STATIC void execinterp(char **, char **); STATIC void printentry(struct tblentry *, int);
STATIC void printentry(struct tblentry *);
STATIC void clearcmdentry(int);
STATIC struct tblentry *cmdlookup(char *, int); STATIC struct tblentry *cmdlookup(char *, int);
STATIC void delete_cmd_entry(void); STATIC void delete_cmd_entry(void);
#else STATIC void addcmdentry(char *, struct cmdentry *);
STATIC void tryexec();
STATIC void execinterp();
STATIC void printentry();
STATIC void clearcmdentry();
STATIC struct tblentry *cmdlookup();
STATIC void delete_cmd_entry();
#endif
@ -113,9 +111,7 @@ STATIC void delete_cmd_entry();
*/ */
void void
shellexec(argv, envp, path, index) shellexec(char **argv, char **envp, char *path, int index)
char **argv, **envp;
char *path;
{ {
char *cmdname; char *cmdname;
int e; int e;
@ -134,40 +130,37 @@ shellexec(argv, envp, path, index)
stunalloc(cmdname); 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 STATIC void
tryexec(cmd, argv, envp) tryexec(char *cmd, char **argv, char **envp)
char *cmd;
char **argv;
char **envp;
{ {
int e; int e;
char *p;
#ifdef SYSV
do {
execve(cmd, argv, envp); execve(cmd, argv, envp);
} while (errno == EINTR); #if !__minix_vmd
#else
execve(cmd, argv, envp);
#endif
#if HASHBANG
e = errno; e = errno;
if (e == ENOEXEC) { if (e == ENOEXEC) {
initshellproc(); initshellproc();
setinputfile(cmd, 0); setinputfile(cmd, 0);
commandname = arg0 = savestr(argv[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); setparam(argv + 1);
exraise(EXSHELLPROC); exraise(EXSHELLPROC);
/*NOTREACHED*/ /*NOTREACHED*/
@ -176,88 +169,6 @@ tryexec(cmd, argv, envp)
#endif #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 * 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 * set to the start of the path before the first call; padvance will update
@ -271,11 +182,9 @@ break2:;
char *pathopt; char *pathopt;
char * char *
padvance(path, name) padvance(char **path, char *name)
char **path;
char *name;
{ {
register char *p, *q; char *p, *q;
char *start; char *start;
int len; int len;
@ -288,7 +197,7 @@ padvance(path, name)
growstackblock(); growstackblock();
q = stackblock(); q = stackblock();
if (p != start) { if (p != start) {
bcopy(start, q, p - start); memcpy(q, start, p - start);
q += p - start; q += p - start;
*q++ = '/'; *q++ = '/';
} }
@ -310,7 +219,9 @@ padvance(path, name)
/*** Command hashing code ***/ /*** Command hashing code ***/
hashcmd(argc, argv) char **argv; { int
hashcmd(int argc __unused, char **argv __unused)
{
struct tblentry **pp; struct tblentry **pp;
struct tblentry *cmdp; struct tblentry *cmdp;
int c; int c;
@ -318,14 +229,6 @@ hashcmd(argc, argv) char **argv; {
struct cmdentry entry; struct cmdentry entry;
char *name; 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; verbose = 0;
while ((c = nextopt("rv")) != '\0') { while ((c = nextopt("rv")) != '\0') {
if (c == 'r') { if (c == 'r') {
@ -334,16 +237,28 @@ hashcmd(argc, argv) char **argv; {
verbose++; 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) { while ((name = *argptr) != NULL) {
if ((cmdp = cmdlookup(name, 0)) != NULL if ((cmdp = cmdlookup(name, 0)) != NULL
&& (cmdp->cmdtype == CMDNORMAL && (cmdp->cmdtype == CMDNORMAL
|| cmdp->cmdtype == CMDBUILTIN && builtinloc >= 0)) || (cmdp->cmdtype == CMDBUILTIN && builtinloc >= 0)))
delete_cmd_entry(); delete_cmd_entry();
find_command(name, &entry, 1); find_command(name, &entry, 1, pathval());
if (verbose) { if (verbose) {
if (entry.cmdtype != CMDUNKNOWN) { /* if no error msg */ if (entry.cmdtype != CMDUNKNOWN) { /* if no error msg */
cmdp = cmdlookup(name, 0); cmdp = cmdlookup(name, 0);
printentry(cmdp); if (cmdp != NULL)
printentry(cmdp, verbose);
else
outfmt(&errout, "%s: not found\n", name);
} }
flushall(); flushall();
} }
@ -354,8 +269,7 @@ hashcmd(argc, argv) char **argv; {
STATIC void STATIC void
printentry(cmdp) printentry(struct tblentry *cmdp, int verbose)
struct tblentry *cmdp;
{ {
int index; int index;
char *path; char *path;
@ -373,6 +287,14 @@ printentry(cmdp)
out1fmt("builtin %s", cmdp->cmdname); out1fmt("builtin %s", cmdp->cmdname);
} else if (cmdp->cmdtype == CMDFUNCTION) { } else if (cmdp->cmdtype == CMDFUNCTION) {
out1fmt("function %s", cmdp->cmdname); out1fmt("function %s", cmdp->cmdname);
if (verbose) {
INTOFF;
name = commandtext(cmdp->param.func);
out1c(' ');
out1str(name);
ckfree(name);
INTON;
}
#if DEBUG #if DEBUG
} else { } else {
error("internal error: cmdtype %d", cmdp->cmdtype); error("internal error: cmdtype %d", cmdp->cmdtype);
@ -391,14 +313,11 @@ printentry(cmdp)
*/ */
void void
find_command(name, entry, printerr) find_command(char *name, struct cmdentry *entry, int printerr, char *path)
char *name;
struct cmdentry *entry;
{ {
struct tblentry *cmdp; struct tblentry *cmdp;
int index; int index;
int prev; int prev;
char *path;
char *fullname; char *fullname;
struct stat statb; struct stat statb;
int e; int e;
@ -434,7 +353,6 @@ find_command(name, entry, printerr)
prev = cmdp->param.index; prev = cmdp->param.index;
} }
path = pathval();
e = ENOENT; e = ENOENT;
index = -1; index = -1;
loop: loop:
@ -464,17 +382,13 @@ loop:
TRACE(("searchexec \"%s\": no change\n", name)); TRACE(("searchexec \"%s\": no change\n", name));
goto success; goto success;
} }
while (stat(fullname, &statb) < 0) { if (stat(fullname, &statb) < 0) {
#ifdef SYSV
if (errno == EINTR)
continue;
#endif
if (errno != ENOENT && errno != ENOTDIR) if (errno != ENOENT && errno != ENOTDIR)
e = errno; e = errno;
goto loop; goto loop;
} }
e = EACCES; /* if we fail, this will be the error */ 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; goto loop;
if (pathopt) { /* this is a %func directory */ if (pathopt) { /* this is a %func directory */
stalloc(strlen(fullname) + 1); stalloc(strlen(fullname) + 1);
@ -484,6 +398,7 @@ loop:
stunalloc(fullname); stunalloc(fullname);
goto success; goto success;
} }
#ifdef notdef
if (statb.st_uid == geteuid()) { if (statb.st_uid == geteuid()) {
if ((statb.st_mode & 0100) == 0) if ((statb.st_mode & 0100) == 0)
goto loop; goto loop;
@ -491,23 +406,10 @@ loop:
if ((statb.st_mode & 010) == 0) if ((statb.st_mode & 010) == 0)
goto loop; goto loop;
} else { } 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) if ((statb.st_mode & 01) == 0)
goto loop; goto loop;
} }
#endif
TRACE(("searchexec \"%s\" returns \"%s\"\n", name, fullname)); TRACE(("searchexec \"%s\" returns \"%s\"\n", name, fullname));
INTOFF; INTOFF;
cmdp = cmdlookup(name, 1); cmdp = cmdlookup(name, 1);
@ -520,8 +422,12 @@ loop:
/* We failed. If there was an entry for this command, delete it */ /* We failed. If there was an entry for this command, delete it */
if (cmdp) if (cmdp)
delete_cmd_entry(); delete_cmd_entry();
if (printerr) if (printerr) {
outfmt(out2, "%s: %s\n", name, errmsg(e, E_EXEC)); if (e == ENOENT || e == ENOTDIR)
outfmt(out2, "%s: not found\n", name);
else
outfmt(out2, "%s: %s\n", name, strerror(e));
}
entry->cmdtype = CMDUNKNOWN; entry->cmdtype = CMDUNKNOWN;
return; return;
@ -538,10 +444,9 @@ success:
*/ */
int int
find_builtin(name) find_builtin(char *name)
char *name;
{ {
const register struct builtincmd *bp; const struct builtincmd *bp;
for (bp = builtincmd ; bp->name ; bp++) { for (bp = builtincmd ; bp->name ; bp++) {
if (*bp->name == *name && equal(bp->name, name)) if (*bp->name == *name && equal(bp->name, name))
@ -558,14 +463,15 @@ find_builtin(name)
*/ */
void void
hashcd() { hashcd(void)
{
struct tblentry **pp; struct tblentry **pp;
struct tblentry *cmdp; struct tblentry *cmdp;
for (pp = cmdtable ; pp < &cmdtable[CMDTABLESIZE] ; pp++) { for (pp = cmdtable ; pp < &cmdtable[CMDTABLESIZE] ; pp++) {
for (cmdp = *pp ; cmdp ; cmdp = cmdp->next) { for (cmdp = *pp ; cmdp ; cmdp = cmdp->next) {
if (cmdp->cmdtype == CMDNORMAL if (cmdp->cmdtype == CMDNORMAL
|| cmdp->cmdtype == CMDBUILTIN && builtinloc >= 0) || (cmdp->cmdtype == CMDBUILTIN && builtinloc >= 0))
cmdp->rehash = 1; cmdp->rehash = 1;
} }
} }
@ -580,10 +486,9 @@ hashcd() {
*/ */
void void
changepath(newval) changepath(const char *newval)
char *newval;
{ {
char *old, *new; const char *old, *new;
int index; int index;
int firstchange; int firstchange;
int bltin; int bltin;
@ -596,8 +501,8 @@ changepath(newval)
for (;;) { for (;;) {
if (*old != *new) { if (*old != *new) {
firstchange = index; firstchange = index;
if (*old == '\0' && *new == ':' if ((*old == '\0' && *new == ':')
|| *old == ':' && *new == '\0') || (*old == ':' && *new == '\0'))
firstchange++; firstchange++;
old = new; /* ignore subsequent differences */ old = new; /* ignore subsequent differences */
} }
@ -624,8 +529,9 @@ changepath(newval)
* PATH which has changed. * PATH which has changed.
*/ */
STATIC void void
clearcmdentry(firstchange) { clearcmdentry(int firstchange)
{
struct tblentry **tblp; struct tblentry **tblp;
struct tblentry **pp; struct tblentry **pp;
struct tblentry *cmdp; struct tblentry *cmdp;
@ -634,8 +540,10 @@ clearcmdentry(firstchange) {
for (tblp = cmdtable ; tblp < &cmdtable[CMDTABLESIZE] ; tblp++) { for (tblp = cmdtable ; tblp < &cmdtable[CMDTABLESIZE] ; tblp++) {
pp = tblp; pp = tblp;
while ((cmdp = *pp) != NULL) { while ((cmdp = *pp) != NULL) {
if (cmdp->cmdtype == CMDNORMAL && cmdp->param.index >= firstchange if ((cmdp->cmdtype == CMDNORMAL &&
|| cmdp->cmdtype == CMDBUILTIN && builtinloc >= firstchange) { cmdp->param.index >= firstchange)
|| (cmdp->cmdtype == CMDBUILTIN &&
builtinloc >= firstchange)) {
*pp = cmdp->next; *pp = cmdp->next;
ckfree(cmdp); ckfree(cmdp);
} else { } else {
@ -652,15 +560,15 @@ clearcmdentry(firstchange) {
*/ */
#ifdef mkinit #ifdef mkinit
MKINIT void deletefuncs(); INCLUDE "exec.h"
SHELLPROC { SHELLPROC {
deletefuncs(); deletefuncs();
} }
#endif #endif
void void
deletefuncs() { deletefuncs(void)
{
struct tblentry **tblp; struct tblentry **tblp;
struct tblentry **pp; struct tblentry **pp;
struct tblentry *cmdp; struct tblentry *cmdp;
@ -691,15 +599,14 @@ deletefuncs() {
* entry. * entry.
*/ */
struct tblentry **lastcmdentry; STATIC struct tblentry **lastcmdentry;
STATIC struct tblentry * STATIC struct tblentry *
cmdlookup(name, add) cmdlookup(char *name, int add)
char *name;
{ {
int hashval; int hashval;
register char *p; char *p;
struct tblentry *cmdp; struct tblentry *cmdp;
struct tblentry **pp; struct tblentry **pp;
@ -728,13 +635,13 @@ cmdlookup(name, add)
return cmdp; return cmdp;
} }
/* /*
* Delete the command entry returned on the last lookup. * Delete the command entry returned on the last lookup.
*/ */
STATIC void STATIC void
delete_cmd_entry() { delete_cmd_entry(void)
{
struct tblentry *cmdp; struct tblentry *cmdp;
INTOFF; INTOFF;
@ -746,34 +653,13 @@ 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 * Add a new command entry, replacing any existing command entry for
* the same name. * the same name.
*/ */
void static void
addcmdentry(name, entry) addcmdentry(char *name, struct cmdentry *entry)
char *name;
struct cmdentry *entry;
{ {
struct tblentry *cmdp; struct tblentry *cmdp;
@ -793,9 +679,7 @@ addcmdentry(name, entry)
*/ */
void void
defun(name, func) defun(char *name, union node *func)
char *name;
union node *func;
{ {
struct cmdentry entry; struct cmdentry entry;
@ -811,14 +695,98 @@ defun(name, func)
* Delete a function if it exists. * Delete a function if it exists.
*/ */
void int
unsetfunc(name) unsetfunc(char *name)
char *name;
{ {
struct tblentry *cmdp; struct tblentry *cmdp;
if ((cmdp = cmdlookup(name, 0)) != NULL && cmdp->cmdtype == CMDFUNCTION) { if ((cmdp = cmdlookup(name, 0)) != NULL && cmdp->cmdtype == CMDFUNCTION) {
freefunc(cmdp->param.func); freefunc(cmdp->param.func);
delete_cmd_entry(); 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 $
*/

View file

@ -1,6 +1,6 @@
/*- /*-
* Copyright (c) 1991 The Regents of the University of California. * Copyright (c) 1991, 1993
* All rights reserved. * The Regents of the University of California. All rights reserved.
* *
* This code is derived from software contributed to Berkeley by * This code is derived from software contributed to Berkeley by
* Kenneth Almquist. * Kenneth Almquist.
@ -13,10 +13,6 @@
* 2. Redistributions in binary form must reproduce the above copyright * 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the * notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution. * 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 * 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 * may be used to endorse or promote products derived from this software
* without specific prior written permission. * without specific prior written permission.
@ -33,7 +29,8 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE. * 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 */ /* values of cmdtype */
@ -53,23 +50,21 @@ struct cmdentry {
extern char *pathopt; /* set by padvance */ extern char *pathopt; /* set by padvance */
extern int exerrno; /* last exec error */
#ifdef __STDC__
void shellexec(char **, char **, char *, int); void shellexec(char **, char **, char *, int);
char *padvance(char **, char *); 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 *); int find_builtin(char *);
void hashcd(void); void hashcd(void);
void changepath(char *); void changepath(const char *);
void deletefuncs(void);
void defun(char *, union node *); void defun(char *, union node *);
void unsetfunc(char *); int unsetfunc(char *);
#else int typecmd(int, char **);
void shellexec(); void clearcmdentry(int);
char *padvance();
void find_command(); /*
int find_builtin(); * $PchId: exec.h,v 1.5 2006/04/10 14:47:34 philip Exp $
void hashcd(); */
void changepath();
void defun();
void unsetfunc();
#endif

File diff suppressed because it is too large Load diff

View file

@ -1,6 +1,6 @@
/*- /*-
* Copyright (c) 1991 The Regents of the University of California. * Copyright (c) 1991, 1993
* All rights reserved. * The Regents of the University of California. All rights reserved.
* *
* This code is derived from software contributed to Berkeley by * This code is derived from software contributed to Berkeley by
* Kenneth Almquist. * Kenneth Almquist.
@ -13,10 +13,6 @@
* 2. Redistributions in binary form must reproduce the above copyright * 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the * notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution. * 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 * 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 * may be used to endorse or promote products derived from this software
* without specific prior written permission. * without specific prior written permission.
@ -33,7 +29,8 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE. * 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 { struct strlist {
@ -47,17 +44,24 @@ struct arglist {
struct strlist **lastp; 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; union node;
void expandarg(union node *, struct arglist *, int);
void expandhere(union node *, 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 *); void rmescapes(char *);
int casematch(union node *, char *); int casematch(union node *, char *);
#else int wordexpcmd(int, char **);
void expandarg();
void expandhere(); /*
int patmatch(); * $PchId: expand.h,v 1.4 2006/03/30 14:50:52 philip Exp $
void rmescapes(); */
int casematch();
#endif

View file

@ -1,5 +1,5 @@
# Copyright (c) 1991 The Regents of the University of California. # Copyright (c) 1991, 1993
# All rights reserved. # The Regents of the University of California. All rights reserved.
# #
# This code is derived from software contributed to Berkeley by # This code is derived from software contributed to Berkeley by
# Kenneth Almquist. # Kenneth Almquist.
@ -12,10 +12,6 @@
# 2. Redistributions in binary form must reproduce the above copyright # 2. Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the # notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution. # 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 # 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 # may be used to endorse or promote products derived from this software
# without specific prior written permission. # without specific prior written permission.
@ -32,7 +28,8 @@
# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF # OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
# SUCH DAMAGE. # 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. # Conditional move--don't replace an existing file.
@ -47,3 +44,6 @@ cmv() {
fi fi
/bin/mv "$1" "$2" /bin/mv "$1" "$2"
} }
#
# $PchId: cmv,v 1.2 2006/03/29 10:43:18 philip Exp $

View file

@ -1,5 +1,5 @@
# Copyright (c) 1991 The Regents of the University of California. # Copyright (c) 1991, 1993
# All rights reserved. # The Regents of the University of California. All rights reserved.
# #
# This code is derived from software contributed to Berkeley by # This code is derived from software contributed to Berkeley by
# Kenneth Almquist. # Kenneth Almquist.
@ -12,10 +12,6 @@
# 2. Redistributions in binary form must reproduce the above copyright # 2. Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the # notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution. # 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 # 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 # may be used to endorse or promote products derived from this software
# without specific prior written permission. # without specific prior written permission.
@ -32,7 +28,8 @@
# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF # OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
# SUCH DAMAGE. # 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 # pushd, popd, and dirs --- written by Chris Bertin
# Pixel Computer Inc. ...!wjh12!pixel!pixutl!chris # Pixel Computer Inc. ...!wjh12!pixel!pixutl!chris
@ -71,3 +68,6 @@ dirs () {
echo "`pwd` $DSTACK" echo "`pwd` $DSTACK"
return 0 return 0
} }
#
# $PchId: dirs,v 1.2 2006/03/29 10:43:18 philip Exp $

View file

@ -1,5 +1,5 @@
# Copyright (c) 1991 The Regents of the University of California. # Copyright (c) 1991, 1993
# All rights reserved. # The Regents of the University of California. All rights reserved.
# #
# This code is derived from software contributed to Berkeley by # This code is derived from software contributed to Berkeley by
# Kenneth Almquist. # Kenneth Almquist.
@ -12,10 +12,6 @@
# 2. Redistributions in binary form must reproduce the above copyright # 2. Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the # notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution. # 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 # 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 # may be used to endorse or promote products derived from this software
# without specific prior written permission. # without specific prior written permission.
@ -32,7 +28,8 @@
# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF # OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
# SUCH DAMAGE. # 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. # Convert job names to process ids and then run /bin/kill.
@ -47,3 +44,6 @@ kill() {
done done
/bin/kill $args /bin/kill $args
} }
#
# $PchId: kill,v 1.2 2006/03/29 10:43:18 philip Exp $

View file

@ -1,5 +1,5 @@
# Copyright (c) 1991 The Regents of the University of California. # Copyright (c) 1991, 1993
# All rights reserved. # The Regents of the University of California. All rights reserved.
# #
# This code is derived from software contributed to Berkeley by # This code is derived from software contributed to Berkeley by
# Kenneth Almquist. # Kenneth Almquist.
@ -12,10 +12,6 @@
# 2. Redistributions in binary form must reproduce the above copyright # 2. Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the # notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution. # 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 # 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 # may be used to endorse or promote products derived from this software
# without specific prior written permission. # without specific prior written permission.
@ -32,7 +28,11 @@
# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF # OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
# SUCH DAMAGE. # 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 # replaces the login builtin in the BSD shell
login () exec login "$@" login () exec login "$@"
#
# $PchId: login,v 1.2 2006/03/29 10:43:18 philip Exp $

View file

@ -1,5 +1,5 @@
# Copyright (c) 1991 The Regents of the University of California. # Copyright (c) 1991, 1993
# All rights reserved. # The Regents of the University of California. All rights reserved.
# #
# This code is derived from software contributed to Berkeley by # This code is derived from software contributed to Berkeley by
# Kenneth Almquist. # Kenneth Almquist.
@ -12,10 +12,6 @@
# 2. Redistributions in binary form must reproduce the above copyright # 2. Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the # notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution. # 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 # 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 # may be used to endorse or promote products derived from this software
# without specific prior written permission. # without specific prior written permission.
@ -32,6 +28,10 @@
# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF # OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
# SUCH DAMAGE. # 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 "$@" newgrp() exec newgrp "$@"
#
# $PchId: newgrp,v 1.2 2006/03/29 10:43:18 philip Exp $

View file

@ -1,5 +1,5 @@
# Copyright (c) 1991 The Regents of the University of California. # Copyright (c) 1991, 1993
# All rights reserved. # The Regents of the University of California. All rights reserved.
# #
# This code is derived from software contributed to Berkeley by # This code is derived from software contributed to Berkeley by
# Kenneth Almquist. # Kenneth Almquist.
@ -12,10 +12,6 @@
# 2. Redistributions in binary form must reproduce the above copyright # 2. Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the # notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution. # 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 # 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 # may be used to endorse or promote products derived from this software
# without specific prior written permission. # without specific prior written permission.
@ -32,7 +28,8 @@
# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF # OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
# SUCH DAMAGE. # 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 # pushd, popd, and dirs --- written by Chris Bertin
# Pixel Computer Inc. ...!wjh12!pixel!pixutl!chris # Pixel Computer Inc. ...!wjh12!pixel!pixutl!chris
@ -71,3 +68,6 @@ dirs () {
echo "`pwd` $DSTACK" echo "`pwd` $DSTACK"
return 0 return 0
} }
#
# $PchId: popd,v 1.2 2006/03/29 10:43:18 philip Exp $

View file

@ -1,5 +1,5 @@
# Copyright (c) 1991 The Regents of the University of California. # Copyright (c) 1991, 1993
# All rights reserved. # The Regents of the University of California. All rights reserved.
# #
# This code is derived from software contributed to Berkeley by # This code is derived from software contributed to Berkeley by
# Kenneth Almquist. # Kenneth Almquist.
@ -12,10 +12,6 @@
# 2. Redistributions in binary form must reproduce the above copyright # 2. Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the # notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution. # 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 # 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 # may be used to endorse or promote products derived from this software
# without specific prior written permission. # without specific prior written permission.
@ -32,7 +28,8 @@
# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF # OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
# SUCH DAMAGE. # 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 # pushd, popd, and dirs --- written by Chris Bertin
# Pixel Computer Inc. ...!wjh12!pixel!pixutl!chris # Pixel Computer Inc. ...!wjh12!pixel!pixutl!chris
@ -71,3 +68,6 @@ dirs () {
echo "`pwd` $DSTACK" echo "`pwd` $DSTACK"
return 0 return 0
} }
#
# $PchId: pushd,v 1.2 2006/03/29 10:43:18 philip Exp $

View file

@ -1,5 +1,5 @@
# Copyright (c) 1991 The Regents of the University of California. # Copyright (c) 1991, 1993
# All rights reserved. # The Regents of the University of California. All rights reserved.
# #
# This code is derived from software contributed to Berkeley by # This code is derived from software contributed to Berkeley by
# Kenneth Almquist. # Kenneth Almquist.
@ -12,10 +12,6 @@
# 2. Redistributions in binary form must reproduce the above copyright # 2. Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the # notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution. # 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 # 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 # may be used to endorse or promote products derived from this software
# without specific prior written permission. # without specific prior written permission.
@ -32,10 +28,14 @@
# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF # OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
# SUCH DAMAGE. # 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() { suspend() {
local - local -
set +j set +j
kill -TSTP 0 kill -TSTP 0
} }
#
# $PchId: suspend,v 1.2 2006/03/29 10:43:18 philip Exp $

533
commands/ash/histedit.c Normal file
View 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 $
*/

View file

@ -1,6 +1,6 @@
/*- /*-
* Copyright (c) 1991 The Regents of the University of California. * Copyright (c) 1991, 1993
* All rights reserved. * The Regents of the University of California. All rights reserved.
* *
* This code is derived from software contributed to Berkeley by * This code is derived from software contributed to Berkeley by
* Kenneth Almquist. * Kenneth Almquist.
@ -13,10 +13,6 @@
* 2. Redistributions in binary form must reproduce the above copyright * 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the * notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution. * 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 * 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 * may be used to endorse or promote products derived from this software
* without specific prior written permission. * without specific prior written permission.
@ -33,15 +29,14 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE. * 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 init(void);
void reset(void); void reset(void);
void initshellproc(void); void initshellproc(void);
#else
void init(); /*
void reset(); * $PchId: init.h,v 1.3 2006/03/30 14:31:06 philip Exp $
void initshellproc(); */
#endif

View file

@ -1,6 +1,6 @@
/*- /*-
* Copyright (c) 1991 The Regents of the University of California. * Copyright (c) 1991, 1993
* All rights reserved. * The Regents of the University of California. All rights reserved.
* *
* This code is derived from software contributed to Berkeley by * This code is derived from software contributed to Berkeley by
* Kenneth Almquist. * Kenneth Almquist.
@ -13,10 +13,6 @@
* 2. Redistributions in binary form must reproduce the above copyright * 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the * notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution. * 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 * 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 * may be used to endorse or promote products derived from this software
* without specific prior written permission. * without specific prior written permission.
@ -35,26 +31,61 @@
*/ */
#ifndef lint #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 */ #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. * This file implements the input routines used by the parser.
*/ */
#include <sys/types.h>
#include <stdio.h> /* defines BUFSIZ */
#include "shell.h" #include "shell.h"
#include <fcntl.h> #include "redir.h"
#include <errno.h>
#include "syntax.h" #include "syntax.h"
#include "input.h" #include "input.h"
#include "output.h" #include "output.h"
#include "options.h"
#include "memalloc.h" #include "memalloc.h"
#include "error.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 */ #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 * 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 MKINIT
struct parsefile { struct parsefile {
struct parsefile *prev; /* preceding file on stack */
int linno; /* current line */ int linno; /* current line */
int fd; /* file descriptor (or -1 if string) */ 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 */ char *nextc; /* next char in buffer */
struct parsefile *prev; /* preceding file on stack */
char *buf; /* input buffer */ 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 */ int plinno = 1; /* input line number */
MKINIT int parsenleft; /* copy of parsefile->nleft */ MKINIT int parsenleft; /* copy of parsefile->nleft */
MKINIT int parselleft; /* copy of parsefile->lleft */
char *parsenextc; /* copy of parsefile->nextc */ char *parsenextc; /* copy of parsefile->nextc */
MKINIT struct parsefile basepf; /* top level input file */ MKINIT struct parsefile basepf; /* top level input file */
char basebuf[BUFSIZ]; /* buffer for top level input file */ char basebuf[BUFSIZ]; /* buffer for top level input file */
struct parsefile *parsefile = &basepf; /* current input file */ STATIC struct parsefile *parsefile = &basepf; /* current input file */
char *pushedstring; /* copy of parsenextc when text pushed back */ int init_editline = 0; /* editline library initialized? */
int pushednleft; /* copy of parsenleft when text pushed back */ int whichprompt; /* -1 == PSE, 1 == PS1, 2 == PS2 */
#if READLINE #ifndef EDITLINE
char *readline __P((const char *prompt)); EditLine *el; /* cookie for editline package */
char *r_use_prompt = NULL; /* the prompt to use with readline */
#endif #endif
#ifdef __STDC__
STATIC void pushfile(void); STATIC void pushfile(void);
#else static int preadfd(void);
STATIC void pushfile();
#endif
#ifdef mkinit #ifdef mkinit
INCLUDE "input.h" INCLUDE "input.h"
@ -106,7 +135,7 @@ INIT {
RESET { RESET {
if (exception != EXSHELLPROC) if (exception != EXSHELLPROC)
parsenleft = 0; /* clear input buffer */ parselleft = parsenleft = 0; /* clear input buffer */
popallfiles(); popallfiles();
} }
@ -121,10 +150,9 @@ SHELLPROC {
*/ */
char * char *
pfgets(line, len) pfgets(char *line, int len)
char *line;
{ {
register char *p = line; char *p = line;
int nleft = len; int nleft = len;
int c; int c;
@ -151,64 +179,74 @@ pfgets(line, len)
*/ */
int int
pgetc() { pgetc(void)
{
return pgetc_macro(); return pgetc_macro();
} }
/* static int
* Refill the input buffer and return the next input character: preadfd(void)
* {
* 1) If a string was pushed back on the input, switch back to the regular int nr;
* buffer. parsenextc = parsefile->buf;
* 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.
*/
int #if !defined(NO_HISTORY) && !defined(EDITLINE)
preadbuffer() { if (el != NULL && gotwinch) {
register char *p, *q; gotwinch = 0;
register int i; el_resize(el);
if (pushedstring) {
parsenextc = pushedstring;
pushedstring = NULL;
parsenleft = pushednleft;
if (--parsenleft >= 0)
return *parsenextc++;
} }
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 #endif
retry: retry:
p = parsenextc = parsefile->buf; #ifndef NO_HISTORY
i = read(parsefile->fd, p, BUFSIZ); #ifdef EDITLINE
if (i <= 0) { if (parsefile->fd == 0) {
if (i < 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) if (errno == EINTR)
goto retry; goto retry;
#ifdef EWOULDBLOCK #ifdef EWOULDBLOCK
@ -222,35 +260,106 @@ retry:
} }
} }
} }
#endif #endif /* EWOULDBLOCK */
} }
parsenleft = EOF_NLEFT; nr = -1;
}
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; return PEOF;
} }
#if READLINE
} }
#endif
parsenleft = i - 1; q = p = parsenextc;
/* delete nul characters */ /* delete nul characters */
for (;;) { something = 0;
if (*p++ == '\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; 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++;
} }
*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. * Undo the last call to pgetc. Only one character may be pushed back.
@ -258,28 +367,57 @@ retry:
*/ */
void void
pungetc() { pungetc(void)
{
parsenleft++; parsenleft++;
parsenextc--; parsenextc--;
} }
/* /*
* Push a string back onto the input. This code doesn't work if the user * Push a string back onto the input at this current parsefile level.
* tries to push back more than one string at once. * We handle aliases this way.
*/ */
void void
ppushback(string, length) pushstring(char *s, int len, void *ap)
char *string;
{ {
pushedstring = parsenextc; struct strpush *sp;
pushednleft = parsenleft;
parsenextc = string; INTOFF;
parsenleft = length; /*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 * Set the input to take input from a file. If push is set, push the
@ -287,17 +425,16 @@ ppushback(string, length)
*/ */
void void
setinputfile(fname, push) setinputfile(char *fname, int push)
char *fname;
{ {
int fd; int fd;
int fd2; int fd2;
INTOFF; INTOFF;
if ((fd = open(fname, O_RDONLY)) < 0) 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) { if (fd < 10) {
fd2 = copyfd(fd, 10); fd2 = fcntl(fd, F_DUPFD, 10);
close(fd); close(fd);
if (fd2 < 0) if (fd2 < 0)
error("Out of file descriptors"); error("Out of file descriptors");
@ -314,8 +451,9 @@ setinputfile(fname, push)
*/ */
void void
setinputfd(fd, push) { setinputfd(int fd, int push)
(void) fcntl(fd, F_SETFD, fcntl(fd, F_GETFD) | FD_CLOEXEC); {
(void)fcntl(fd, F_SETFD, FD_CLOEXEC);
if (push) { if (push) {
pushfile(); pushfile();
parsefile->buf = ckmalloc(BUFSIZ); parsefile->buf = ckmalloc(BUFSIZ);
@ -325,7 +463,7 @@ setinputfd(fd, push) {
parsefile->fd = fd; parsefile->fd = fd;
if (parsefile->buf == NULL) if (parsefile->buf == NULL)
parsefile->buf = ckmalloc(BUFSIZ); parsefile->buf = ckmalloc(BUFSIZ);
parsenleft = 0; parselleft = parsenleft = 0;
plinno = 1; plinno = 1;
} }
@ -335,14 +473,13 @@ setinputfd(fd, push) {
*/ */
void void
setinputstring(string, push) setinputstring(char *string, int push)
char *string;
{ {
INTOFF; INTOFF;
if (push) if (push)
pushfile(); pushfile();
parsenextc = string; parsenextc = string;
parsenleft = strlen(string); parselleft = parsenleft = strlen(string);
parsefile->buf = NULL; parsefile->buf = NULL;
plinno = 1; plinno = 1;
INTON; INTON;
@ -356,21 +493,26 @@ setinputstring(string, push)
*/ */
STATIC void STATIC void
pushfile() { pushfile(void)
{
struct parsefile *pf; struct parsefile *pf;
parsefile->nleft = parsenleft; parsefile->nleft = parsenleft;
parsefile->lleft = parselleft;
parsefile->nextc = parsenextc; parsefile->nextc = parsenextc;
parsefile->linno = plinno; parsefile->linno = plinno;
pf = (struct parsefile *)ckmalloc(sizeof (struct parsefile)); pf = (struct parsefile *)ckmalloc(sizeof (struct parsefile));
pf->prev = parsefile; pf->prev = parsefile;
pf->fd = -1; pf->fd = -1;
pf->strpush = NULL;
pf->basestrpush.prev = NULL;
parsefile = pf; parsefile = pf;
} }
void void
popfile() { popfile(void)
{
struct parsefile *pf = parsefile; struct parsefile *pf = parsefile;
INTOFF; INTOFF;
@ -378,9 +520,12 @@ popfile() {
close(pf->fd); close(pf->fd);
if (pf->buf) if (pf->buf)
ckfree(pf->buf); ckfree(pf->buf);
while (pf->strpush)
popstring();
parsefile = pf->prev; parsefile = pf->prev;
ckfree(pf); ckfree(pf);
parsenleft = parsefile->nleft; parsenleft = parsefile->nleft;
parselleft = parsefile->lleft;
parsenextc = parsefile->nextc; parsenextc = parsefile->nextc;
plinno = parsefile->linno; plinno = parsefile->linno;
INTON; INTON;
@ -392,7 +537,8 @@ popfile() {
*/ */
void void
popallfiles() { popallfiles(void)
{
while (parsefile != &basepf) while (parsefile != &basepf)
popfile(); popfile();
} }
@ -405,10 +551,15 @@ popallfiles() {
*/ */
void void
closescript() { closescript(void)
{
popallfiles(); popallfiles();
if (parsefile->fd > 0) { if (parsefile->fd > 0) {
close(parsefile->fd); close(parsefile->fd);
parsefile->fd = 0; parsefile->fd = 0;
} }
} }
/*
* $PchId: input.c,v 1.6 2006/05/23 12:00:32 philip Exp $
*/

View file

@ -1,6 +1,6 @@
/*- /*-
* Copyright (c) 1991 The Regents of the University of California. * Copyright (c) 1991, 1993
* All rights reserved. * The Regents of the University of California. All rights reserved.
* *
* This code is derived from software contributed to Berkeley by * This code is derived from software contributed to Berkeley by
* Kenneth Almquist. * Kenneth Almquist.
@ -13,10 +13,6 @@
* 2. Redistributions in binary form must reproduce the above copyright * 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the * notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution. * 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 * 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 * may be used to endorse or promote products derived from this software
* without specific prior written permission. * without specific prior written permission.
@ -33,7 +29,8 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE. * 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 */ /* PEOF (the end of file marker) is defined in syntax.h */
@ -46,39 +43,22 @@
extern int plinno; extern int plinno;
extern int parsenleft; /* number of characters left in input buffer */ extern int parsenleft; /* number of characters left in input buffer */
extern char *parsenextc; /* next character 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); char *pfgets(char *, int);
int pgetc(void); int pgetc(void);
int preadbuffer(void); int preadbuffer(void);
void pungetc(void); void pungetc(void);
void ppushback(char *, int); void pushstring(char *, int, void *);
void setinputfile(char *, int); void setinputfile(char *, int);
void setinputfd(int, int); void setinputfd(int, int);
void setinputstring(char *, int); void setinputstring(char *, int);
void popfile(void); void popfile(void);
void popallfiles(void); void popallfiles(void);
void closescript(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()) #define pgetc_macro() (--parsenleft >= 0? *parsenextc++ : preadbuffer())
#if READLINE /*
/* The variable "r_use_prompt" indicates the prompt to use with readline, * $PchId: input.h,v 1.3 2006/03/30 13:49:37 philip Exp $
* *and* that readline may only be used if non-NULL.
*/ */
extern char *r_use_prompt;
#endif

File diff suppressed because it is too large Load diff

View file

@ -1,6 +1,6 @@
/*- /*-
* Copyright (c) 1991 The Regents of the University of California. * Copyright (c) 1991, 1993
* All rights reserved. * The Regents of the University of California. All rights reserved.
* *
* This code is derived from software contributed to Berkeley by * This code is derived from software contributed to Berkeley by
* Kenneth Almquist. * Kenneth Almquist.
@ -13,10 +13,6 @@
* 2. Redistributions in binary form must reproduce the above copyright * 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the * notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution. * 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 * 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 * may be used to endorse or promote products derived from this software
* without specific prior written permission. * without specific prior written permission.
@ -33,7 +29,8 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE. * 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. */ /* Mode argument to forkshell. Don't change FORK_FG or FORK_BG. */
@ -41,6 +38,7 @@
#define FORK_BG 1 #define FORK_BG 1
#define FORK_NOJOB 2 #define FORK_NOJOB 2
#include <signal.h> /* for sig_atomic_t */
/* /*
* A job structure contains information about a job. A job is either a * A job structure contains information about a job. A job is either a
@ -51,7 +49,7 @@
struct procstat { struct procstat {
pid_t pid; /* process id */ pid_t pid; /* process id */
short status; /* status flags (defined above) */ int status; /* status flags (defined above) */
char *cmd; /* text of command being run */ char *cmd; /* text of command being run */
}; };
@ -64,33 +62,41 @@ struct procstat {
struct job { struct job {
struct procstat ps0; /* status of process */ struct procstat ps0; /* status of process */
struct procstat *ps; /* status or processes when more than one */ 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 */ pid_t pgrp; /* process group of this job */
char state; /* true if job is finished */ char state; /* true if job is finished */
char used; /* true if this entry is in used */ char used; /* true if this entry is in used */
char changed; /* true if status has changed */ char changed; /* true if status has changed */
char foreground; /* true if running in the foreground */
#if JOBS #if JOBS
char jobctl; /* job running under job control */ char jobctl; /* job running under job control */
struct job *next; /* job used after this one */
#endif #endif
}; };
extern pid_t backgndpid; /* pid of last background process */ 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 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); struct job *makejob(union node *, int);
int forkshell(struct job *, union node *, int); pid_t forkshell(struct job *, union node *, int);
int waitforjob(struct job *); int waitforjob(struct job *, int *);
#else int stoppedjobs(void);
void setjobctl(); char *commandtext(union node *);
void showjobs();
struct job *makejob();
int forkshell();
int waitforjob();
#endif
#if ! JOBS #if ! JOBS
#define setjobctl(on) /* do nothing */ #define setjobctl(on) /* do nothing */
#endif #endif
/*
* $PchId: jobs.h,v 1.4 2006/03/30 12:07:24 philip Exp $
*/

View file

@ -1,6 +1,6 @@
/*- /*-
* Copyright (c) 1991 The Regents of the University of California. * Copyright (c) 1991, 1993
* All rights reserved. * The Regents of the University of California. All rights reserved.
* *
* This code is derived from software contributed to Berkeley by * This code is derived from software contributed to Berkeley by
* Kenneth Almquist. * Kenneth Almquist.
@ -33,7 +33,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE. * 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; 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 #endif
/*
* $PchId: machdep.h,v 1.2 2001/05/15 16:36:26 philip Exp $
*/

View file

@ -1,6 +1,6 @@
/*- /*-
* Copyright (c) 1991 The Regents of the University of California. * Copyright (c) 1991, 1993
* All rights reserved. * The Regents of the University of California. All rights reserved.
* *
* This code is derived from software contributed to Berkeley by * This code is derived from software contributed to Berkeley by
* Kenneth Almquist. * Kenneth Almquist.
@ -13,10 +13,6 @@
* 2. Redistributions in binary form must reproduce the above copyright * 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the * notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution. * 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 * 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 * may be used to endorse or promote products derived from this software
* without specific prior written permission. * without specific prior written permission.
@ -35,8 +31,14 @@
*/ */
#ifndef lint #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 */ #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?) * 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 "output.h"
#include "memalloc.h" #include "memalloc.h"
#include "error.h" #include "error.h"
#include "mail.h"
#include <sys/types.h> #include <sys/types.h>
#include <sys/stat.h> #include <sys/stat.h>
#include <stdlib.h>
#define MAXMBOXES 10 #define MAXMBOXES 10
@ -67,11 +71,12 @@ STATIC time_t mailtime[MAXMBOXES]; /* times of mailboxes */
*/ */
void void
chkmail(silent) { chkmail(int silent)
register int i; {
int i;
char *mpath; char *mpath;
char *p; char *p;
register char *q; char *q;
struct stackmark smark; struct stackmark smark;
struct stat statb; struct stat statb;
@ -91,18 +96,28 @@ chkmail(silent) {
if (q[-1] != '/') if (q[-1] != '/')
abort(); abort();
q[-1] = '\0'; /* delete trailing '/' */ q[-1] = '\0'; /* delete trailing '/' */
#ifdef notdef /* this is what the System V shell claims to do (it lies) */
if (stat(p, &statb) < 0) if (stat(p, &statb) < 0)
statb.st_mtime = 0; statb.st_mtime = 0;
if (!silent if (statb.st_mtime > mailtime[i] && ! silent) {
&& statb.st_size > 0 out2str(pathopt? pathopt : "you have mail");
&& statb.st_mtime > mailtime[i]
&& statb.st_mtime > statb.st_atime
) {
out2str(pathopt? pathopt : "You have mail");
out2c('\n'); out2c('\n');
} }
mailtime[i] = statb.st_mtime; 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; nmboxes = i;
popstackmark(&smark); popstackmark(&smark);
} }
/*
* $PchId: mail.c,v 1.5 2006/05/22 12:02:37 philip Exp $
*/

View file

@ -1,6 +1,6 @@
/*- /*-
* Copyright (c) 1991 The Regents of the University of California. * Copyright (c) 1991, 1993
* All rights reserved. * The Regents of the University of California. All rights reserved.
* *
* This code is derived from software contributed to Berkeley by * This code is derived from software contributed to Berkeley by
* Kenneth Almquist. * Kenneth Almquist.
@ -13,10 +13,6 @@
* 2. Redistributions in binary form must reproduce the above copyright * 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the * notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution. * 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 * 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 * may be used to endorse or promote products derived from this software
* without specific prior written permission. * without specific prior written permission.
@ -33,11 +29,12 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE. * 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); void chkmail(int);
#else
void chkmail(); /*
#endif * $PchId: mail.h,v 1.3 2006/03/30 11:53:44 philip Exp $
*/

View file

@ -1,6 +1,6 @@
/*- /*-
* Copyright (c) 1991 The Regents of the University of California. * Copyright (c) 1991, 1993
* All rights reserved. * The Regents of the University of California. All rights reserved.
* *
* This code is derived from software contributed to Berkeley by * This code is derived from software contributed to Berkeley by
* Kenneth Almquist. * Kenneth Almquist.
@ -13,10 +13,6 @@
* 2. Redistributions in binary form must reproduce the above copyright * 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the * notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution. * 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 * 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 * may be used to endorse or promote products derived from this software
* without specific prior written permission. * without specific prior written permission.
@ -35,18 +31,29 @@
*/ */
#ifndef lint #ifndef lint
char copyright[] = static char const copyright[] =
"@(#) Copyright (c) 1991 The Regents of the University of California.\n\ "@(#) Copyright (c) 1991, 1993\n\
All rights reserved.\n"; The Regents of the University of California. All rights reserved.\n";
#endif /* not lint */ #endif /* not lint */
#ifndef 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 */ #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 <signal.h>
#include <sys/stat.h>
#include <unistd.h>
#include <fcntl.h> #include <fcntl.h>
#include <locale.h>
#include <errno.h>
#include "shell.h" #include "shell.h"
#include "main.h" #include "main.h"
#include "mail.h" #include "mail.h"
@ -54,38 +61,26 @@ static char sccsid[] = "@(#)main.c 5.2 (Berkeley) 3/13/91";
#include "output.h" #include "output.h"
#include "parser.h" #include "parser.h"
#include "nodes.h" #include "nodes.h"
#include "expand.h"
#include "eval.h" #include "eval.h"
#include "jobs.h" #include "jobs.h"
#include "input.h" #include "input.h"
#include "trap.h" #include "trap.h"
#if ATTY
#include "var.h" #include "var.h"
#endif #include "show.h"
#include "memalloc.h" #include "memalloc.h"
#include "error.h" #include "error.h"
#include "init.h" #include "init.h"
#include "mystring.h" #include "mystring.h"
#include "exec.h"
#define PROFILE 0 #include "cd.h"
#include "builtins.h"
int rootpid; int rootpid;
int rootshell; 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 *); STATIC void read_profile(char *);
char *getenv(char *); STATIC char *find_dot_file(char *);
#else
STATIC void read_profile();
char *getenv();
#endif
/* /*
* Main routine. We initialize things, parse the arguments, execute * 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. * 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 jmploc jmploc;
struct stackmark smark; struct stackmark smark;
volatile int state; volatile int state;
char *shinit, *home; char *shinit;
char *profile = NULL, *ashrc = NULL;
#if PROFILE (void) setlocale(LC_ALL, "");
monitor(4, etext, profile_buf, sizeof profile_buf, 50);
#endif
state = 0; state = 0;
if (setjmp(jmploc.loc)) { if (setjmp(jmploc.loc)) {
/* /*
@ -112,21 +106,32 @@ main(argc, argv) char **argv; {
* exception EXSHELLPROC to clean up before executing * exception EXSHELLPROC to clean up before executing
* the shell procedure. * the shell procedure.
*/ */
if (exception == EXSHELLPROC) { switch (exception) {
case EXSHELLPROC:
rootpid = getpid(); rootpid = getpid();
rootshell = 1; rootshell = 1;
minusc = NULL; minusc = NULL;
state = 3; state = 3;
} else if (state == 0 || iflag == 0 || ! rootshell) break;
exitshell(2);
case EXEXEC:
exitstatus = exerrno;
break;
case EXERROR:
exitstatus = 2;
break;
default:
break;
}
if (exception != EXSHELLPROC) {
if (state == 0 || iflag == 0 || ! rootshell)
exitshell(exitstatus);
}
reset(); reset();
#if ATTY if (exception == EXINT) {
if (exception == EXINT
&& (! attyset() || equal(termval(), "emacs")))
#else
if (exception == EXINT)
#endif
{
out2c('\n'); out2c('\n');
flushout(&errout); flushout(&errout);
} }
@ -151,57 +156,38 @@ main(argc, argv) char **argv; {
init(); init();
setstackmark(&smark); setstackmark(&smark);
procargs(argc, argv); procargs(argc, argv);
if (eflag) eflag = 2; /* Truly enable [ex]flag after init. */ if (getpwd() == NULL && iflag)
if (xflag) xflag = 2; out2str("sh: cannot determine working directory\n");
if (argv[0] && argv[0][0] == '-') { if (argv[0] && argv[0][0] == '-') {
state = 1; state = 1;
read_profile("/etc/profile"); read_profile("/etc/profile");
state1: state1:
state = 2; state = 2;
if ((home = getenv("HOME")) != NULL if (privileged == 0)
&& (profile = (char *) malloc(strlen(home) + 10)) != NULL)
{
strcpy(profile, home);
strcat(profile, "/.profile");
read_profile(profile);
} else {
read_profile(".profile"); read_profile(".profile");
} else
} else if ((sflag || minusc) && (shinit = getenv("SHINIT")) != NULL) { read_profile("/etc/suid_profile");
state = 2;
evalstring(shinit);
} }
state2: state2:
if (profile != NULL) free(profile);
state = 3; state = 3;
if (!argv[0] || argv[0][0] != '-') { if (!privileged && iflag) {
if ((home = getenv("HOME")) != NULL if ((shinit = lookupvar("ENV")) != NULL && *shinit != '\0') {
&& (ashrc = (char *) malloc(strlen(home) + 8)) != NULL) state = 3;
{ read_profile(shinit);
strcpy(ashrc, home);
strcat(ashrc, "/.ashrc");
read_profile(ashrc);
} }
} }
state3: 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; state = 4;
if (minusc) { if (minusc) {
evalstring(minusc); evalstring(minusc);
} }
if (sflag || minusc == NULL) { if (sflag || minusc == NULL) {
state4: state4: /* XXX ??? - why isn't this before the "if" statement */
cmdloop(1); cmdloop(1);
} }
#if PROFILE
monitor(0);
#endif
exitshell(exitstatus); exitshell(exitstatus);
/*NOTREACHED*/
return 0;
} }
@ -211,52 +197,49 @@ state4:
*/ */
void void
cmdloop(top) { cmdloop(int top)
{
union node *n; union node *n;
struct stackmark smark; struct stackmark smark;
int inter; int inter;
int numeof; int numeof = 0;
TRACE(("cmdloop(%d) called\n", top)); TRACE(("cmdloop(%d) called\n", top));
setstackmark(&smark); setstackmark(&smark);
numeof = 0;
for (;;) { for (;;) {
if (pendingsigs) if (pendingsigs)
dotrap(); dotrap();
inter = 0; inter = 0;
if (iflag && top) { if (iflag && top) {
inter++; inter++;
showjobs(1); showjobs(1, 0, 0);
chkmail(0); chkmail(0);
flushout(&output); flushout(&output);
} }
n = parsecmd(inter); n = parsecmd(inter);
#if DEBUG /* showtree(n); DEBUG */
/* showtree(n); */
#endif
if (n == NEOF) { if (n == NEOF) {
if (Iflag == 0 || numeof >= 50) if (!top || numeof >= 50)
break;
if (!stoppedjobs()) {
if (!Iflag)
break; break;
out2str("\nUse \"exit\" to leave shell.\n"); out2str("\nUse \"exit\" to leave shell.\n");
}
numeof++; numeof++;
} else if (n != NULL && nflag == 0) { } else if (n != NULL && nflag == 0) {
if (inter) { job_warning = (job_warning == 2) ? 1 : 0;
INTOFF; numeof = 0;
if (prevcmd)
freefunc(prevcmd);
prevcmd = curcmd;
curcmd = copyfunc(n);
INTON;
}
evaltree(n, 0); evaltree(n, 0);
#ifdef notdef
if (exitstatus) /*DEBUG*/
outfmt(&errout, "Exit status 0x%X\n", exitstatus);
#endif
} }
popstackmark(&smark); popstackmark(&smark);
setstackmark(&smark);
if (evalskip == SKIPFILE) {
evalskip = 0;
break;
} }
popstackmark(&smark); /* unnecessary */ }
popstackmark(&smark);
} }
@ -266,8 +249,7 @@ cmdloop(top) {
*/ */
STATIC void STATIC void
read_profile(name) read_profile(char *name)
char *name;
{ {
int fd; int fd;
@ -288,8 +270,7 @@ read_profile(name)
*/ */
void void
readcmdfile(name) readcmdfile(char *name)
char *name;
{ {
int fd; int fd;
@ -297,23 +278,55 @@ readcmdfile(name)
if ((fd = open(name, O_RDONLY)) >= 0) if ((fd = open(name, O_RDONLY)) >= 0)
setinputfd(fd, 1); setinputfd(fd, 1);
else else
error("Can't open %s", name); error("Can't open %s: %s", name, strerror(errno));
INTON; INTON;
cmdloop(0); cmdloop(0);
popfile(); popfile();
} }
/* /*
* Take commands from a file. To be compatable we should do a path * Take commands from a file. To be compatible we should do a path
* search for the file, but a path search doesn't make any sense. * 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; exitstatus = 0;
for (sp = cmdenviron; sp ; sp = sp->next)
setvareq(savestr(sp->text), VSTRFIXED|VTEXTFIXED);
if (argc >= 2) { /* That's what SVR2 does */ if (argc >= 2) { /* That's what SVR2 does */
setinputfile(argv[1], 1); char *fullname = find_dot_file(argv[1]);
commandname = argv[1];
setinputfile(fullname, 1);
commandname = fullname;
cmdloop(0); cmdloop(0);
popfile(); popfile();
} }
@ -321,40 +334,22 @@ dotcmd(argc, argv) char **argv; {
} }
exitcmd(argc, argv) char **argv; { int
exitcmd(int argc, char **argv)
{
extern int oexitstatus; extern int oexitstatus;
if (stoppedjobs())
return 0;
if (argc > 1) if (argc > 1)
exitstatus = number(argv[1]); exitstatus = number(argv[1]);
else else
exitstatus = oexitstatus; exitstatus = oexitstatus;
exitshell(exitstatus); exitshell(exitstatus);
} /*NOTREACHED*/
lccmd(argc, argv) char **argv; {
if (argc > 1) {
defun(argv[1], prevcmd);
return 0; 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

View file

@ -1,6 +1,6 @@
/*- /*-
* Copyright (c) 1991 The Regents of the University of California. * Copyright (c) 1991, 1993
* All rights reserved. * The Regents of the University of California. All rights reserved.
* *
* This code is derived from software contributed to Berkeley by * This code is derived from software contributed to Berkeley by
* Kenneth Almquist. * Kenneth Almquist.
@ -13,10 +13,6 @@
* 2. Redistributions in binary form must reproduce the above copyright * 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the * notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution. * 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 * 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 * may be used to endorse or promote products derived from this software
* without specific prior written permission. * without specific prior written permission.
@ -33,16 +29,18 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE. * 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 rootpid; /* pid of main shell */
extern int rootshell; /* true if we aren't a child of the main shell */ extern int rootshell; /* true if we aren't a child of the main shell */
#ifdef __STDC__
void readcmdfile(char *); void readcmdfile(char *);
void cmdloop(int); void cmdloop(int);
#else int dotcmd(int, char **);
void readcmdfile(); int exitcmd(int, char **);
void cmdloop();
#endif /*
* $PchId: main.h,v 1.3 2006/03/30 11:43:59 philip Exp $
*/

View file

@ -1,6 +1,6 @@
/*- /*-
* Copyright (c) 1991 The Regents of the University of California. * Copyright (c) 1991, 1993
* All rights reserved. * The Regents of the University of California. All rights reserved.
* *
* This code is derived from software contributed to Berkeley by * This code is derived from software contributed to Berkeley by
* Kenneth Almquist. * Kenneth Almquist.
@ -13,10 +13,6 @@
* 2. Redistributions in binary form must reproduce the above copyright * 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the * notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution. * 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 * 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 * may be used to endorse or promote products derived from this software
* without specific prior written permission. * without specific prior written permission.
@ -35,24 +31,33 @@
*/ */
#ifndef lint #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 */ #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 "shell.h"
#include "output.h" #include "output.h"
#include "machdep.h"
#include "memalloc.h" #include "memalloc.h"
#include "error.h" #include "error.h"
#include "machdep.h"
#include "mystring.h" #include "mystring.h"
#include "expand.h"
#include <stdlib.h>
#include <unistd.h>
/* /*
* Like malloc, but returns an error when out of space. * Like malloc, but returns an error when out of space.
*/ */
pointer pointer
ckmalloc(nbytes) { ckmalloc(int nbytes)
register pointer p; {
pointer malloc(); pointer p;
if ((p = malloc(nbytes)) == NULL) if ((p = malloc(nbytes)) == NULL)
error("Out of space"); error("Out of space");
@ -65,11 +70,8 @@ ckmalloc(nbytes) {
*/ */
pointer pointer
ckrealloc(p, nbytes) ckrealloc(pointer p, int nbytes)
register pointer p;
{ {
pointer realloc();
if ((p = realloc(p, nbytes)) == NULL) if ((p = realloc(p, nbytes)) == NULL)
error("Out of space"); error("Out of space");
return p; return p;
@ -81,10 +83,9 @@ ckrealloc(p, nbytes)
*/ */
char * char *
savestr(s) savestr(char *s)
char *s;
{ {
register char *p; char *p;
p = ckmalloc(strlen(s) + 1); p = ckmalloc(strlen(s) + 1);
scopy(s, p); scopy(s, p);
@ -97,47 +98,56 @@ savestr(s)
* to make this more efficient, and also to avoid all sorts of exception * to make this more efficient, and also to avoid all sorts of exception
* handling code to handle interrupts in the middle of a parse. * handling code to handle interrupts in the middle of a parse.
* *
* The size 504 was chosen because the Ultrix malloc handles that size * The size 496 was chosen because with 16-byte alignment the total size
* well. * 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 {
struct stack_block *prev; struct stack_block *prev;
char space[MINSIZE]; /* Data follows */
}; };
#define SPACE(sp) ((char*)(sp) + ALIGN(sizeof(struct stack_block)))
struct stack_block stackbase; STATIC struct stack_block *stackp;
struct stack_block *stackp = &stackbase; STATIC struct stackmark *markp;
char *stacknxt = stackbase.space; char *stacknxt;
int stacknleft = MINSIZE; int stacknleft;
int sstrnleft; int sstrnleft;
int herefd = -1; int herefd = -1;
static void
pointer stnewblock(int nbytes)
stalloc(nbytes) { {
register char *p;
nbytes = ALIGN(nbytes);
if (nbytes > stacknleft) {
int blocksize;
struct stack_block *sp; struct stack_block *sp;
int allocsize;
if (nbytes < MINSIZE)
nbytes = MINSIZE;
allocsize = ALIGN(sizeof(struct stack_block)) + ALIGN(nbytes);
blocksize = nbytes;
if (blocksize < MINSIZE)
blocksize = MINSIZE;
INTOFF; INTOFF;
sp = ckmalloc(sizeof(struct stack_block) - MINSIZE + blocksize); sp = ckmalloc(allocsize);
sp->prev = stackp; sp->prev = stackp;
stacknxt = sp->space; stacknxt = SPACE(sp);
stacknleft = blocksize; stacknleft = allocsize - (stacknxt - (char*)sp);
stackp = sp; stackp = sp;
INTON; INTON;
} }
pointer
stalloc(int nbytes)
{
char *p;
nbytes = ALIGN(nbytes);
if (nbytes > stacknleft)
stnewblock(nbytes);
p = stacknxt; p = stacknxt;
stacknxt += nbytes; stacknxt += nbytes;
stacknleft -= nbytes; stacknleft -= nbytes;
@ -146,11 +156,10 @@ stalloc(nbytes) {
void void
stunalloc(p) stunalloc(pointer p)
pointer p;
{ {
if (p == NULL) { /*DEBUG */ if (p == NULL) { /*DEBUG */
write(2, "stunalloc\n", 10); write(STDERR_FILENO, "stunalloc\n", 10);
abort(); abort();
} }
stacknleft += stacknxt - (char *)p; stacknleft += stacknxt - (char *)p;
@ -160,22 +169,23 @@ stunalloc(p)
void void
setstackmark(mark) setstackmark(struct stackmark *mark)
struct stackmark *mark;
{ {
mark->stackp = stackp; mark->stackp = stackp;
mark->stacknxt = stacknxt; mark->stacknxt = stacknxt;
mark->stacknleft = stacknleft; mark->stacknleft = stacknleft;
mark->marknext = markp;
markp = mark;
} }
void void
popstackmark(mark) popstackmark(struct stackmark *mark)
struct stackmark *mark;
{ {
struct stack_block *sp; struct stack_block *sp;
INTOFF; INTOFF;
markp = mark->marknext;
while (stackp != mark->stackp) { while (stackp != mark->stackp) {
sp = stackp; sp = stackp;
stackp = sp->prev; stackp = sp->prev;
@ -198,35 +208,56 @@ popstackmark(mark)
*/ */
void void
growstackblock() { growstackblock(void)
{
char *p; char *p;
int newlen = stacknleft * 2 + 100; int newlen;
char *oldspace = stacknxt; char *oldspace;
int oldlen = stacknleft; int oldlen;
struct stack_block *sp; 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; INTOFF;
sp = stackp; oldstackp = stackp;
stackp = sp->prev; stackp = oldstackp->prev;
sp = ckrealloc((pointer)sp, sizeof(struct stack_block) - MINSIZE + newlen); sp = ckrealloc((pointer)oldstackp, newlen);
sp->prev = stackp; sp->prev = stackp;
stackp = sp; stackp = sp;
stacknxt = sp->space; stacknxt = SPACE(sp);
stacknleft = newlen; 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; INTON;
} else { } else {
p = stalloc(newlen); p = stalloc(newlen);
bcopy(oldspace, p, oldlen); if (oldlen != 0)
stacknxt = p; /* free the space */ memcpy(p, oldspace, oldlen);
stacknleft += newlen; /* we just allocated */ stunalloc(p);
} }
} }
void void
grabstackblock(len) { grabstackblock(int len)
{
len = ALIGN(len); len = ALIGN(len);
stacknxt += len; stacknxt += len;
stacknleft -= len; stacknleft -= len;
@ -254,8 +285,11 @@ grabstackblock(len) {
char * char *
growstackstr() { growstackstr(void)
int len = stackblocksize(); {
int len;
len = stackblocksize();
if (herefd >= 0 && len >= 1024) { if (herefd >= 0 && len >= 1024) {
xwrite(herefd, stackblock(), len); xwrite(herefd, stackblock(), len);
sstrnleft = len - 1; sstrnleft = len - 1;
@ -272,8 +306,11 @@ growstackstr() {
*/ */
char * char *
makestrspace() { makestrspace(void)
int len = stackblocksize() - sstrnleft; {
int len;
len = stackblocksize() - sstrnleft;
growstackblock(); growstackblock();
sstrnleft = stackblocksize() - len; sstrnleft = stackblocksize() - len;
return stackblock() + len; return stackblock() + len;
@ -282,11 +319,13 @@ makestrspace() {
void void
ungrabstackstr(s, p) ungrabstackstr(char *s, char *p)
char *s;
char *p;
{ {
stacknleft += stacknxt - s; stacknleft += stacknxt - s;
stacknxt = s; stacknxt = s;
sstrnleft = stacknleft - (p - s); sstrnleft = stacknleft - (p - s);
} }
/*
* $PchId: memalloc.c,v 1.5 2006/05/22 12:03:26 philip Exp $
*/

View file

@ -1,6 +1,6 @@
/*- /*-
* Copyright (c) 1991 The Regents of the University of California. * Copyright (c) 1991, 1993
* All rights reserved. * The Regents of the University of California. All rights reserved.
* *
* This code is derived from software contributed to Berkeley by * This code is derived from software contributed to Berkeley by
* Kenneth Almquist. * Kenneth Almquist.
@ -13,10 +13,6 @@
* 2. Redistributions in binary form must reproduce the above copyright * 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the * notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution. * 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 * 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 * may be used to endorse or promote products derived from this software
* without specific prior written permission. * without specific prior written permission.
@ -33,13 +29,15 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE. * 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 stackmark {
struct stack_block *stackp; struct stack_block *stackp;
char *stacknxt; char *stacknxt;
int stacknleft; int stacknleft;
struct stackmark *marknext;
}; };
@ -48,10 +46,8 @@ extern int stacknleft;
extern int sstrnleft; extern int sstrnleft;
extern int herefd; extern int herefd;
#ifdef __STDC__
pointer ckmalloc(int); pointer ckmalloc(int);
pointer ckrealloc(pointer, int); pointer ckrealloc(pointer, int);
void free(pointer); /* defined in C library */
char *savestr(char *); char *savestr(char *);
pointer stalloc(int); pointer stalloc(int);
void stunalloc(pointer); void stunalloc(pointer);
@ -62,21 +58,6 @@ void grabstackblock(int);
char *growstackstr(void); char *growstackstr(void);
char *makestrspace(void); char *makestrspace(void);
void ungrabstackstr(char *, char *); 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 stackblocksize() stacknleft
#define STARTSTACKSTR(p) p = stackblock(), sstrnleft = stackblocksize() #define STARTSTACKSTR(p) p = stackblock(), sstrnleft = stackblocksize()
#define STPUTC(c, p) (--sstrnleft >= 0? (*p++ = (c)) : (p = growstackstr(), *p++ = (c))) #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 USTPUTC(c, p) (--sstrnleft, *p++ = (c))
#define STACKSTRNUL(p) (sstrnleft == 0? (p = growstackstr(), *p = '\0') : (*p = '\0')) #define STACKSTRNUL(p) (sstrnleft == 0? (p = growstackstr(), *p = '\0') : (*p = '\0'))
#define STUNPUTC(p) (++sstrnleft, --p) #define STUNPUTC(p) (++sstrnleft, --p)
@ -93,3 +74,7 @@ void ungrabstackstr();
#define grabstackstr(p) stalloc(stackblocksize() - sstrnleft) #define grabstackstr(p) stalloc(stackblocksize() - sstrnleft)
#define ckfree(p) free((pointer)(p)) #define ckfree(p) free((pointer)(p))
/*
* $PchId: memalloc.h,v 1.3 2006/03/30 11:39:41 philip Exp $
*/

View file

@ -1,6 +1,6 @@
/*- /*-
* Copyright (c) 1991 The Regents of the University of California. * Copyright (c) 1991, 1993
* All rights reserved. * The Regents of the University of California. All rights reserved.
* *
* This code is derived from software contributed to Berkeley by * This code is derived from software contributed to Berkeley by
* Kenneth Almquist. * Kenneth Almquist.
@ -13,10 +13,6 @@
* 2. Redistributions in binary form must reproduce the above copyright * 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the * notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution. * 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 * 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 * may be used to endorse or promote products derived from this software
* without specific prior written permission. * without specific prior written permission.
@ -35,13 +31,32 @@
*/ */
#ifndef lint #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 */ #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 "shell.h"
#include "options.h" #include "options.h"
#include "var.h" #include "var.h"
@ -49,38 +64,71 @@ static char sccsid[] = "@(#)miscbltin.c 5.2 (Berkeley) 3/13/91";
#include "memalloc.h" #include "memalloc.h"
#include "error.h" #include "error.h"
#include "mystring.h" #include "mystring.h"
#include "builtins.h"
#undef eflag #undef eflag
extern char **argptr; /* argument list for builtin command */
/* /*
* The read builtin. The -e option causes backslashes to escape the * The read builtin. The -r option causes backslashes to be treated like
* following character. * ordinary characters.
* *
* This uses unbuffered input, which may be avoidable in some cases. * 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; char **ap;
int backslash; int backslash;
char c; char c;
int eflag; int rflag;
char *prompt; char *prompt;
char *ifs; char *ifs;
char *p; char *p;
int startword; int startword;
int status; int status;
int i; 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; prompt = NULL;
while ((i = nextopt("ep:")) != '\0') { tv.tv_sec = -1;
if (i == 'p') tv.tv_usec = 0;
prompt = optarg; while ((i = nextopt("erp:t:")) != '\0') {
else switch(i) {
eflag = 1; 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)) { if (prompt && isatty(0)) {
out2str(prompt); out2str(prompt);
@ -90,12 +138,45 @@ readcmd(argc, argv) char **argv; {
error("arg count"); error("arg count");
if ((ifs = bltinlookup("IFS", 1)) == NULL) if ((ifs = bltinlookup("IFS", 1)) == NULL)
ifs = nullstr; 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; status = 0;
startword = 1; startword = 1;
backslash = 0; backslash = 0;
STARTSTACKSTR(p); STARTSTACKSTR(p);
for (;;) { for (;;) {
if (read(0, &c, 1) != 1) { if (read(STDIN_FILENO, &c, 1) != 1) {
status = 1; status = 1;
break; break;
} }
@ -107,7 +188,7 @@ readcmd(argc, argv) char **argv; {
STPUTC(c, p); STPUTC(c, p);
continue; continue;
} }
if (eflag && c == '\\') { if (!rflag && c == '\\') {
backslash++; backslash++;
continue; continue;
} }
@ -118,7 +199,7 @@ readcmd(argc, argv) char **argv; {
} }
startword = 0; startword = 0;
if (backslash && c == '\\') { if (backslash && c == '\\') {
if (read(0, &c, 1) != 1) { if (read(STDIN_FILENO, &c, 1) != 1) {
status = 1; status = 1;
break; 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; int mask;
char *p;
int i; int i;
int symbolic_mode = 0;
while ((i = nextopt("S")) != '\0') {
symbolic_mode = 1;
}
if ((p = argv[1]) == NULL) {
INTOFF; INTOFF;
mask = umask(0); mask = umask(0);
umask(mask); umask(mask);
INTON; INTON;
out1fmt("%.4o\n", mask); /* %#o might be better */
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 { } else {
out1fmt("%.4o\n", mask);
}
} else {
if (isdigit(*ap)) {
mask = 0; mask = 0;
do { do {
if ((unsigned)(i = *p - '0') >= 8) if (*ap >= '8' || *ap < '0')
error("Illegal number: %s", argv[1]); error("Illegal number: %s", argv[1]);
mask = (mask << 3) + i; mask = (mask << 3) + (*ap - '0');
} while (*++p != '\0'); } while (*++ap != '\0');
umask(mask); 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; 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 $
*/

View file

@ -1,7 +1,7 @@
#!/bin/sh - #!/bin/sh -
# #
# Copyright (c) 1991 The Regents of the University of California. # Copyright (c) 1991, 1993
# All rights reserved. # The Regents of the University of California. All rights reserved.
# #
# This code is derived from software contributed to Berkeley by # This code is derived from software contributed to Berkeley by
# Kenneth Almquist. # Kenneth Almquist.
@ -14,10 +14,6 @@
# 2. Redistributions in binary form must reproduce the above copyright # 2. Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the # notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution. # 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 # 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 # may be used to endorse or promote products derived from this software
# without specific prior written permission. # without specific prior written permission.
@ -34,90 +30,69 @@
# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF # OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
# SUCH DAMAGE. # 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) #temp=`/usr/bin/mktemp -t ka`
temp=/tmp/mkb$$
if [ $# != 2 ] havehist=1
then if [ "X$1" = "X-h" ]; then
echo "USAGE: $0 shell.h builtins" havehist=0
exit 1 shift
fi fi
SHL=$1 havejobs=0
BLTINS=$2 if [ "X$1" = "X-j" ]; then
havejobs=0
temp=/tmp/ka$$ shift
exec > builtins.c elif grep '^#define[ ]*JOBS[ ]*1' $2 > /dev/null
then havejobs=1
fi
objdir=$1
exec > ${objdir}/builtins.c
cat <<\! cat <<\!
/* /*
* This file was generated by the mkbuiltins program. * This file was generated by the mkbuiltins program.
*/ */
#include <stdlib.h>
#include "shell.h" #include "shell.h"
#include "builtins.h" #include "builtins.h"
! !
if grep '^#define JOBS[ ]*1' $SHL > /dev/null awk '/^[^#]/ {if(('$havejobs' || $2 != "-j") && ('$havehist' || $2 != "-h")) \
then print $0}' $3 | sed 's/-[hj]//' > $temp
# Job control. #awk '{ printf "int %s();\n", $1}' $temp
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
echo ' echo '
int (*const builtinfunc[])() = {' int (*const builtinfunc[]) (int, char **) = {'
sed -e 's/ .*// awk '/^[^#]/ { printf "\t%s,\n", $1}' $temp
s/\(.*\)/ \1,/' $temp
echo '}; echo '};
const struct builtincmd builtincmd[] = {' const struct builtincmd builtincmd[] = {'
i=0 awk '{ for (i = 2 ; i <= NF ; i++) {
while read line printf "\t{ \"%s\", %d },\n", $i, NR-1
do }}' $temp
set -$- $line echo ' { NULL, 0 }
shift
for fun
do
echo " \"$fun\", $i,"
done
i=`expr $i + 1`
done < $temp
echo ' NULL, 0
};' };'
exec > builtins.h exec > ${objdir}/builtins.h
cat <<\! cat <<\!
/* /*
* This file was generated by the mkbuiltins program. * This file was generated by the mkbuiltins program.
*/ */
#include <sys/cdefs.h>
! !
i=0
tr abcdefghijklmnopqrstuvwxyz ABCDEFGHIJKLMNOPQRSTUVWXYZ < $temp | tr abcdefghijklmnopqrstuvwxyz ABCDEFGHIJKLMNOPQRSTUVWXYZ < $temp |
while read line awk '{ printf "#define %s %d\n", $1, NR-1}'
do
set -$- $line
echo "#define $1 $i"
i=`expr $i + 1`
done
echo ' echo '
struct builtincmd { struct builtincmd {
char *name; char *name;
int code; int code;
}; };
extern int (*const builtinfunc[])(); extern int (*const builtinfunc[]) (int, char **);
extern const struct builtincmd builtincmd[];' extern const struct builtincmd builtincmd[];'
awk '{ printf "int %s (int, char **);\n", $1 }' < $temp
rm -f $temp rm -f $temp
#
# $PchId: mkbuiltins,v 1.6 2006/05/22 12:42:58 philip Exp $

View file

@ -1,6 +1,6 @@
/*- /*-
* Copyright (c) 1991 The Regents of the University of California. * Copyright (c) 1991, 1993
* All rights reserved. * The Regents of the University of California. All rights reserved.
* *
* This code is derived from software contributed to Berkeley by * This code is derived from software contributed to Berkeley by
* Kenneth Almquist. * Kenneth Almquist.
@ -13,10 +13,6 @@
* 2. Redistributions in binary form must reproduce the above copyright * 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the * notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution. * 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 * 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 * may be used to endorse or promote products derived from this software
* without specific prior written permission. * without specific prior written permission.
@ -35,43 +31,51 @@
*/ */
#ifndef lint #ifndef lint
char copyright[] = static char const copyright[] =
"@(#) Copyright (c) 1991 The Regents of the University of California.\n\ "@(#) Copyright (c) 1991, 1993\n\
All rights reserved.\n"; The Regents of the University of California. All rights reserved.\n";
#endif /* not lint */ #endif /* not lint */
#ifndef 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 */ #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 * This program scans all the source files for code to handle various
* special events and combines this code into one file. This (allegedly) * special events and combines this code into one file. This (allegedly)
* improves the structure of the program since there is no need for * improves the structure of the program since there is no need for
* anyone outside of a module to know that that module performs special * anyone outside of a module to know that that module performs special
* operations on particular events. The command is executed iff init.c * operations on particular events.
* is actually changed.
* *
* Usage: mkinit command sourcefile... * Usage: mkinit sourcefile...
*/ */
#include <sys/cdefs.h>
#include <sys/types.h> #include <sys/types.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.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 * 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 * to the file OUTTEMP, which is then moved to OUTFILE.
* OUTFILE are different.
*/ */
#define OUTFILE "init.c" #define OUTFILE "init.c"
#define OUTTEMP "init.c.new" #define OUTTEMP "init.c.new"
#define OUTOBJ "init.o"
/* /*
@ -148,42 +152,35 @@ struct text decls; /* declarations */
int amiddecls; /* for formatting */ int amiddecls; /* for formatting */
void readfile(), doevent(), doinclude(), dodecl(), output(); static void readfile(char *);
void addstr(), addchar(), writetext(); 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) #define equal(s1, s2) (strcmp(s1, s2) == 0)
FILE *ckfopen(); int
char *savestr(); main(int argc __unused, char *argv[])
void *ckmalloc __P((int));
void error();
main(argc, argv)
char **argv;
{ {
char **ap; char **ap;
int fd;
char c;
if (argc < 2)
error("Usage: mkinit command file...");
header_files[0] = "\"shell.h\""; header_files[0] = "\"shell.h\"";
header_files[1] = "\"mystring.h\""; header_files[1] = "\"mystring.h\"";
for (ap = argv + 2 ; *ap ; ap++) for (ap = argv + 1 ; *ap ; ap++)
readfile(*ap); readfile(*ap);
output(); output();
if (file_changed()) { rename(OUTTEMP, OUTFILE);
unlink(OUTFILE); exit(0);
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");
} }
@ -191,9 +188,8 @@ main(argc, argv)
* Parse an input file. * Parse an input file.
*/ */
void static void
readfile(fname) readfile(char *fname)
char *fname;
{ {
FILE *fp; FILE *fp;
char line[1024]; char line[1024];
@ -215,19 +211,31 @@ readfile(fname)
doinclude(line); doinclude(line);
if (line[0] == 'M' && match("MKINIT", line)) if (line[0] == 'M' && match("MKINIT", line))
dodecl(line, fp); 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); addstr(line, &defines);
} }
}
fclose(fp); fclose(fp);
} }
int static int
match(name, line) match(char *name, char *line)
char *name;
char *line;
{ {
register char *p, *q; char *p, *q;
p = name, q = line; p = name, q = line;
while (*p) { while (*p) {
@ -240,11 +248,10 @@ match(name, line)
} }
int static int
gooddefine(line) gooddefine(char *line)
char *line;
{ {
register char *p; char *p;
if (! match("#define", line)) if (! match("#define", line))
return 0; /* not a define */ return 0; /* not a define */
@ -264,11 +271,8 @@ gooddefine(line)
} }
void static void
doevent(ep, fp, fname) doevent(struct event *ep, FILE *fp, char *fname)
register struct event *ep;
FILE *fp;
char *fname;
{ {
char line[1024]; char line[1024];
int indent; int indent;
@ -304,13 +308,12 @@ doevent(ep, fp, fname)
} }
void static void
doinclude(line) doinclude(char *line)
char *line;
{ {
register char *p; char *p;
char *name; char *name;
register char **pp; char **pp;
for (p = line ; *p != '"' && *p != '<' && *p != '\0' ; p++); for (p = line ; *p != '"' && *p != '<' && *p != '\0' ; p++);
if (*p == '\0') if (*p == '\0')
@ -329,13 +332,11 @@ doinclude(line)
} }
void static void
dodecl(line1, fp) dodecl(char *line1, FILE *fp)
char *line1;
FILE *fp;
{ {
char line[1024]; char line[1024];
register char *p, *q; char *p, *q;
if (strcmp(line1, "MKINIT\n") == 0) { /* start of struct/union decl */ if (strcmp(line1, "MKINIT\n") == 0) { /* start of struct/union decl */
addchar('\n', &decls); addchar('\n', &decls);
@ -350,7 +351,8 @@ dodecl(line1, fp)
if (! amiddecls) if (! amiddecls)
addchar('\n', &decls); addchar('\n', &decls);
q = NULL; q = NULL;
for (p = line1 + 6 ; *p != '=' && *p != '/' ; p++); for (p = line1 + 6 ; *p && strchr("=/\n", *p) == NULL; p++)
continue;
if (*p == '=') { /* eliminate initialization */ if (*p == '=') { /* eliminate initialization */
for (q = p ; *q && *q != ';' ; q++); for (q = p ; *q && *q != ';' ; q++);
if (*q == '\0') if (*q == '\0')
@ -375,8 +377,9 @@ dodecl(line1, fp)
* Write the output to the file OUTTEMP. * Write the output to the file OUTTEMP.
*/ */
void static void
output() { output(void)
{
FILE *fp; FILE *fp;
char **pp; char **pp;
struct event *ep; struct event *ep;
@ -392,7 +395,7 @@ output() {
for (ep = event ; ep->name ; ep++) { for (ep = event ; ep->name ; ep++) {
fputs("\n\n\n", fp); fputs("\n\n\n", fp);
fputs(ep->comment, 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); writetext(&ep->code, fp);
fprintf(fp, "}\n"); fprintf(fp, "}\n");
} }
@ -400,61 +403,14 @@ 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. * 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 * Addstr appends a string to the text struct, and addchar appends a single
* character. * character.
*/ */
void static void
addstr(s, text) addstr(char *s, struct text *text)
register char *s;
register struct text *text;
{ {
while (*s) { while (*s) {
if (--text->nleft < 0) if (--text->nleft < 0)
@ -465,9 +421,8 @@ addstr(s, text)
} }
void static void
addchar(c, text) addchar(int c, struct text *text)
register struct text *text;
{ {
struct block *bp; struct block *bp;
@ -487,10 +442,8 @@ addchar(c, text)
/* /*
* Write the contents of a text structure to a file. * Write the contents of a text structure to a file.
*/ */
void static void
writetext(text, fp) writetext(struct text *text, FILE *fp)
struct text *text;
FILE *fp;
{ {
struct block *bp; struct block *bp;
@ -501,47 +454,47 @@ writetext(text, fp)
} }
} }
FILE * static FILE *
ckfopen(file, mode) ckfopen(char *file, char *mode)
char *file;
char *mode;
{ {
FILE *fp; FILE *fp;
if ((fp = fopen(file, mode)) == NULL) { 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); exit(2);
} }
return fp; return fp;
} }
void * static void *
ckmalloc(nbytes) { ckmalloc(int nbytes)
register char *p; {
char *malloc(); char *p;
if ((p = malloc(nbytes)) == NULL) if ((p = malloc(nbytes)) == NULL)
error("Out of space"); error("Out of space");
return p; return p;
} }
char * static char *
savestr(s) savestr(char *s)
char *s;
{ {
register char *p; char *p;
p = ckmalloc(strlen(s) + 1); p = ckmalloc(strlen(s) + 1);
strcpy(p, s); strcpy(p, s);
return p; return p;
} }
void static void
error(msg) error(char *msg)
char *msg;
{ {
if (curfile != NULL) if (curfile != NULL)
fprintf(stderr, "%s:%d: ", curfile, linno); fprintf(stderr, "%s:%d: ", curfile, linno);
fprintf(stderr, "%s\n", msg); fprintf(stderr, "%s\n", msg);
exit(2); exit(2);
} }
/*
* $PchId: mkinit.c,v 1.6 2006/05/22 12:16:50 philip Exp $
*/

View file

@ -1,6 +1,6 @@
/*- /*-
* Copyright (c) 1991 The Regents of the University of California. * Copyright (c) 1991, 1993
* All rights reserved. * The Regents of the University of California. All rights reserved.
* *
* This code is derived from software contributed to Berkeley by * This code is derived from software contributed to Berkeley by
* Kenneth Almquist. * Kenneth Almquist.
@ -13,10 +13,6 @@
* 2. Redistributions in binary form must reproduce the above copyright * 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the * notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution. * 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 * 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 * may be used to endorse or promote products derived from this software
* without specific prior written permission. * without specific prior written permission.
@ -34,15 +30,20 @@
* SUCH DAMAGE. * SUCH DAMAGE.
*/ */
#if 0
#ifndef lint #ifndef lint
char copyright[] = static char const copyright[] =
"@(#) Copyright (c) 1991 The Regents of the University of California.\n\ "@(#) Copyright (c) 1991, 1993\n\
All rights reserved.\n"; The Regents of the University of California. All rights reserved.\n";
#endif /* not lint */ #endif /* not lint */
#ifndef 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 /* 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 * 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 <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <stdarg.h>
#define MAXTYPES 50 /* max number of node types */ #define MAXTYPES 50 /* max number of node types */
#define MAXFIELDS 20 /* max fields in a structure */ #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 */ static int ntypes; /* number of node types */
char *nodename[MAXTYPES]; /* names of the nodes */ static char *nodename[MAXTYPES]; /* names of the nodes */
struct str *nodestr[MAXTYPES]; /* type of structure used by the node */ static struct str *nodestr[MAXTYPES]; /* type of structure used by the node */
int nstr; /* number of structures */ static int nstr; /* number of structures */
struct str str[MAXTYPES]; /* the structures */ static struct str str[MAXTYPES]; /* the structures */
struct str *curstr; /* current structure */ 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; int
char line[1024]; main(int argc, char *argv[])
int linno;
char *linep;
char *savestr();
#define equal(s1, s2) (strcmp(s1, s2) == 0)
main(argc, argv)
char **argv;
{ {
if (argc != 3) if (argc != 3)
error("usage: mknodes file\n"); error("usage: mknodes file");
infp = stdin;
if ((infp = fopen(argv[1], "r")) == NULL) 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()) { while (readline()) {
if (line[0] == ' ' || line[0] == '\t') if (line[0] == ' ' || line[0] == '\t')
parsefield(); parsefield();
@ -112,12 +127,14 @@ main(argc, argv)
parsenode(); parsenode();
} }
output(argv[2]); output(argv[2]);
return 0; exit(0);
} }
parsenode() { static void
parsenode(void)
{
char name[BUFLEN]; char name[BUFLEN];
char tag[BUFLEN]; char tag[BUFLEN];
struct str *sp; struct str *sp;
@ -131,7 +148,7 @@ parsenode() {
error("Garbage at end of line"); error("Garbage at end of line");
nodename[ntypes] = savestr(name); nodename[ntypes] = savestr(name);
for (sp = str ; sp < str + nstr ; sp++) { for (sp = str ; sp < str + nstr ; sp++) {
if (equal(sp->tag, tag)) if (strcmp(sp->tag, tag) == 0)
break; break;
} }
if (sp >= str + nstr) { if (sp >= str + nstr) {
@ -145,7 +162,9 @@ parsenode() {
} }
parsefield() { static void
parsefield(void)
{
char name[BUFLEN]; char name[BUFLEN];
char type[BUFLEN]; char type[BUFLEN];
char decl[2 * BUFLEN]; char decl[2 * BUFLEN];
@ -159,21 +178,21 @@ parsefield() {
error("No field type"); error("No field type");
fp = &curstr->field[curstr->nfields]; fp = &curstr->field[curstr->nfields];
fp->name = savestr(name); fp->name = savestr(name);
if (equal(type, "nodeptr")) { if (strcmp(type, "nodeptr") == 0) {
fp->type = T_NODE; fp->type = T_NODE;
sprintf(decl, "union node *%s", name); sprintf(decl, "union node *%s", name);
} else if (equal(type, "nodelist")) { } else if (strcmp(type, "nodelist") == 0) {
fp->type = T_NODELIST; fp->type = T_NODELIST;
sprintf(decl, "struct nodelist *%s", name); sprintf(decl, "struct nodelist *%s", name);
} else if (equal(type, "string")) { } else if (strcmp(type, "string") == 0) {
fp->type = T_STRING; fp->type = T_STRING;
sprintf(decl, "char *%s", name); sprintf(decl, "char *%s", name);
} else if (equal(type, "int")) { } else if (strcmp(type, "int") == 0) {
fp->type = T_INT; fp->type = T_INT;
sprintf(decl, "int %s", name); sprintf(decl, "int %s", name);
} else if (equal(type, "other")) { } else if (strcmp(type, "other") == 0) {
fp->type = T_OTHER; fp->type = T_OTHER;
} else if (equal(type, "temp")) { } else if (strcmp(type, "temp") == 0) {
fp->type = T_TEMP; fp->type = T_TEMP;
} else { } else {
error("Unknown type %s", type); error("Unknown type %s", type);
@ -196,8 +215,8 @@ char writer[] = "\
*/\n\ */\n\
\n"; \n";
output(file) static void
char *file; output(char *file)
{ {
FILE *hfile; FILE *hfile;
FILE *cfile; FILE *cfile;
@ -208,9 +227,9 @@ output(file)
char *p; char *p;
if ((patfile = fopen(file, "r")) == NULL) 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) 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) if ((cfile = fopen("nodes.c", "w")) == NULL)
error("Can't create nodes.c"); error("Can't create nodes.c");
fputs(writer, hfile); fputs(writer, hfile);
@ -234,22 +253,17 @@ output(file)
fputs("\tstruct nodelist *next;\n", hfile); fputs("\tstruct nodelist *next;\n", hfile);
fputs("\tunion node *n;\n", hfile); fputs("\tunion node *n;\n", hfile);
fputs("};\n\n\n", hfile); fputs("};\n\n\n", hfile);
fputs("#ifdef __STDC__\n", hfile);
fputs("union node *copyfunc(union node *);\n", hfile); fputs("union node *copyfunc(union node *);\n", hfile);
fputs("void freefunc(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); fputs(writer, cfile);
while (fgets(line, sizeof line, patfile) != NULL) { while (fgets(line, sizeof line, patfile) != NULL) {
for (p = line ; *p == ' ' || *p == '\t' ; p++); for (p = line ; *p == ' ' || *p == '\t' ; p++);
if (equal(p, "%SIZES\n")) if (strcmp(p, "%SIZES\n") == 0)
outsizes(cfile); outsizes(cfile);
else if (equal(p, "%CALCSIZE\n")) else if (strcmp(p, "%CALCSIZE\n") == 0)
outfunc(cfile, 1); outfunc(cfile, 1);
else if (equal(p, "%COPY\n")) else if (strcmp(p, "%COPY\n") == 0)
outfunc(cfile, 0); outfunc(cfile, 0);
else else
fputs(line, cfile); fputs(line, cfile);
@ -258,8 +272,8 @@ output(file)
outsizes(cfile) static void
FILE *cfile; outsizes(FILE *cfile)
{ {
int i; int i;
@ -271,8 +285,8 @@ outsizes(cfile)
} }
outfunc(cfile, calcsize) static void
FILE *cfile; outfunc(FILE *cfile, int calcsize)
{ {
struct str *sp; struct str *sp;
struct field *fp; struct field *fp;
@ -287,8 +301,7 @@ outfunc(cfile, calcsize)
fputs(" funcblocksize += nodesize[n->type];\n", cfile); fputs(" funcblocksize += nodesize[n->type];\n", cfile);
else { else {
fputs(" new = funcblock;\n", cfile); fputs(" new = funcblock;\n", cfile);
fputs(" *(char **)&funcblock += nodesize[n->type];\n", fputs(" funcblock = (char *)funcblock + nodesize[n->type];\n", cfile);
cfile);
} }
fputs(" switch (n->type) {\n", cfile); fputs(" switch (n->type) {\n", cfile);
for (sp = str ; sp < &str[nstr] ; sp++) { for (sp = str ; sp < &str[nstr] ; sp++) {
@ -351,8 +364,8 @@ outfunc(cfile, calcsize)
} }
indent(amount, fp) static void
FILE *fp; indent(int amount, FILE *fp)
{ {
while (amount >= 8) { while (amount >= 8) {
putc('\t', fp); putc('\t', fp);
@ -364,11 +377,10 @@ indent(amount, fp)
} }
int static int
nextfield(buf) nextfield(char *buf)
char *buf;
{ {
register char *p, *q; char *p, *q;
p = linep; p = linep;
while (*p == ' ' || *p == '\t') while (*p == ' ' || *p == '\t')
@ -382,15 +394,18 @@ nextfield(buf)
} }
skipbl() { static void
skipbl(void)
{
while (*linep == ' ' || *linep == '\t') while (*linep == ' ' || *linep == '\t')
linep++; linep++;
} }
int static int
readline() { readline(void)
register char *p; {
char *p;
if (fgets(line, 1024, infp) == NULL) if (fgets(line, 1024, infp) == NULL)
return 0; return 0;
@ -407,26 +422,34 @@ readline() {
error(msg, a1, a2, a3, a4, a5, a6) static void
char *msg; error(const char *msg, ...)
{ {
fprintf(stderr, "line %d: ", linno); va_list va;
fprintf(stderr, msg, a1, a2, a3, a4, a5, a6); va_start(va, msg);
putc('\n', stderr);
(void) fprintf(stderr, "line %d: ", linno);
(void) vfprintf(stderr, msg, va);
(void) fputc('\n', stderr);
va_end(va);
exit(2); exit(2);
} }
char * static char *
savestr(s) savestr(const char *s)
char *s;
{ {
register char *p; char *p;
char *malloc();
if ((p = malloc(strlen(s) + 1)) == NULL) if ((p = malloc(strlen(s) + 1)) == NULL)
error("Out of space"); error("Out of space");
strcpy(p, s); (void) strcpy(p, s);
return p; return p;
} }
/*
* $PchId: mknodes.c,v 1.6 2006/05/23 12:05:14 philip Exp $
*/

View file

@ -1,6 +1,6 @@
/*- /*-
* Copyright (c) 1991 The Regents of the University of California. * Copyright (c) 1991, 1993
* All rights reserved. * The Regents of the University of California. All rights reserved.
* *
* This code is derived from software contributed to Berkeley by * This code is derived from software contributed to Berkeley by
* Kenneth Almquist. * Kenneth Almquist.
@ -35,23 +35,23 @@
*/ */
#ifndef lint #ifndef lint
char copyright[] = static char copyright[] =
"@(#) Copyright (c) 1991 The Regents of the University of California.\n\ "@(#) Copyright (c) 1991, 1993\n\
All rights reserved.\n"; The Regents of the University of California. All rights reserved.\n";
#endif /* not lint */ #endif /* not lint */
#ifndef 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 */ #endif /* not lint */
/* /*
* This program generates the signames.h and signames.c files. * This program generates the signames.h and signames.c files.
*/ */
#include <sys/types.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h>
#include <signal.h> #include <signal.h>
int main(int argc, char *argv[]);
struct sig { struct sig {
int signo; /* signal number */ int signo; /* signal number */
@ -198,3 +198,7 @@ main(argc, argv) char **argv; {
fprintf(cfile, "};\n"); fprintf(cfile, "};\n");
exit(0); exit(0);
} }
/*
* $PchId: mksignames.c,v 1.2 2001/05/14 19:22:26 philip Exp $
*/

View file

@ -1,6 +1,6 @@
/*- /*-
* Copyright (c) 1991 The Regents of the University of California. * Copyright (c) 1991, 1993
* All rights reserved. * The Regents of the University of California. All rights reserved.
* *
* This code is derived from software contributed to Berkeley by * This code is derived from software contributed to Berkeley by
* Kenneth Almquist. * Kenneth Almquist.
@ -13,10 +13,6 @@
* 2. Redistributions in binary form must reproduce the above copyright * 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the * notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution. * 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 * 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 * may be used to endorse or promote products derived from this software
* without specific prior written permission. * without specific prior written permission.
@ -34,23 +30,33 @@
* SUCH DAMAGE. * SUCH DAMAGE.
*/ */
#if 0
#ifndef lint #ifndef lint
char copyright[] = static char const copyright[] =
"@(#) Copyright (c) 1991 The Regents of the University of California.\n\ "@(#) Copyright (c) 1991, 1993\n\
All rights reserved.\n"; The Regents of the University of California. All rights reserved.\n";
#endif /* not lint */ #endif /* not lint */
#ifndef 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 /* 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. * This program creates syntax.h and syntax.c.
*/ */
#include <stdio.h> #include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "parser.h" #include "parser.h"
#ifdef __minix
#define __unused
#endif
struct synclass { struct synclass {
char *name; char *name;
@ -59,19 +65,21 @@ struct synclass {
/* Syntax classes */ /* Syntax classes */
struct synclass synclass[] = { struct synclass synclass[] = {
"CWORD", "character is nothing special", { "CWORD", "character is nothing special" },
"CNL", "newline character", { "CNL", "newline character" },
"CBACK", "a backslash character", { "CBACK", "a backslash character" },
"CSQUOTE", "single quote", { "CSQUOTE", "single quote" },
"CDQUOTE", "double quote", { "CDQUOTE", "double quote" },
"CENDQUOTE", "a terminating quote", { "CENDQUOTE", "a terminating quote" },
"CBQUOTE", "backwards single quote", { "CBQUOTE", "backwards single quote" },
"CVAR", "a dollar sign", { "CVAR", "a dollar sign" },
"CENDVAR", "a '}' character", { "CENDVAR", "a '}' character" },
"CEOF", "end of file", { "CLP", "a left paren in arithmetic" },
"CCTL", "like CWORD, except it must be escaped", { "CRP", "a right paren in arithmetic" },
"CSPCL", "these terminate a word", { "CEOF", "end of file" },
NULL, NULL { "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. * you may have to change the definition of the is_in_name macro.
*/ */
struct synclass is_entry[] = { struct synclass is_entry[] = {
"ISDIGIT", "a digit", { "ISDIGIT", "a digit" },
"ISUPPER", "an upper case letter", { "ISUPPER", "an upper case letter" },
"ISLOWER", "a lower case letter", { "ISLOWER", "a lower case letter" },
"ISUNDER", "an underscore", { "ISUNDER", "an underscore" },
"ISSPECL", "the name of a special parameter", { "ISSPECL", "the name of a special parameter" },
NULL, NULL, { NULL, NULL }
}; };
char writer[] = "\ static char writer[] = "\
/*\n\ /*\n\
* This file was generated by the mksyntax program.\n\ * This file was generated by the mksyntax program.\n\
*/\n\ */\n\
\n"; \n";
FILE *cfile; static FILE *cfile;
FILE *hfile; static FILE *hfile;
char *syntax[513]; static char *syntax[513];
int base; static int base;
int size; /* number of values which a char variable can have */ static int size; /* number of values which a char variable can have */
int nbits; /* number of bits in a character */ static int nbits; /* number of bits in a character */
int digit_contig; /* true if digits are contiguous */ 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 c;
char d; char d;
int sign; int sign;
@ -136,7 +152,9 @@ main() {
if (d == c) if (d == c)
break; break;
} }
#if 0
printf("%s %d bit chars\n", sign? "signed" : "unsigned", nbits); printf("%s %d bit chars\n", sign? "signed" : "unsigned", nbits);
#endif
if (nbits > 9) { if (nbits > 9) {
fputs("Characters can't have more than 9 bits\n", stderr); fputs("Characters can't have more than 9 bits\n", stderr);
exit(2); exit(2);
@ -151,14 +169,14 @@ main() {
digit_contig = 0; digit_contig = 0;
} }
fputs("#include <sys/cdefs.h>\n", hfile); fputs("#include <ctype.h>\n", hfile);
/* Generate the #define statements in the header file */ /* Generate the #define statements in the header file */
fputs("/* Syntax classes */\n", hfile); fputs("/* Syntax classes */\n", hfile);
for (i = 0 ; synclass[i].name ; i++) { for (i = 0 ; synclass[i].name ; i++) {
sprintf(buf, "#define %s %d", synclass[i].name, i); sprintf(buf, "#define %s %d", synclass[i].name, i);
fputs(buf, hfile); 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); putc('\t', hfile);
fprintf(hfile, "/* %s */\n", synclass[i].comment); fprintf(hfile, "/* %s */\n", synclass[i].comment);
} }
@ -167,7 +185,7 @@ main() {
for (i = 0 ; is_entry[i].name ; i++) { for (i = 0 ; is_entry[i].name ; i++) {
sprintf(buf, "#define %s %#o", is_entry[i].name, 1 << i); sprintf(buf, "#define %s %#o", is_entry[i].name, 1 << i);
fputs(buf, hfile); 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); putc('\t', hfile);
fprintf(hfile, "/* %s */\n", is_entry[i].comment); fprintf(hfile, "/* %s */\n", is_entry[i].comment);
} }
@ -178,6 +196,7 @@ main() {
fputs("#define BASESYNTAX (basesyntax + SYNBASE)\n", hfile); fputs("#define BASESYNTAX (basesyntax + SYNBASE)\n", hfile);
fputs("#define DQSYNTAX (dqsyntax + SYNBASE)\n", hfile); fputs("#define DQSYNTAX (dqsyntax + SYNBASE)\n", hfile);
fputs("#define SQSYNTAX (sqsyntax + SYNBASE)\n", hfile); fputs("#define SQSYNTAX (sqsyntax + SYNBASE)\n", hfile);
fputs("#define ARISYNTAX (arisyntax + SYNBASE)\n", hfile);
putc('\n', hfile); putc('\n', hfile);
output_type_macros(); /* is_digit, etc. */ output_type_macros(); /* is_digit, etc. */
putc('\n', hfile); putc('\n', hfile);
@ -204,14 +223,28 @@ main() {
add("`", "CBQUOTE"); add("`", "CBQUOTE");
add("$", "CVAR"); add("$", "CVAR");
add("}", "CENDVAR"); add("}", "CENDVAR");
add("!*?[=", "CCTL"); /* ':/' for tilde expansion, '-' for [a\-x] pattern ranges */
add("!*?[=~:/-", "CCTL");
print("dqsyntax"); print("dqsyntax");
init(); init();
fputs("\n/* syntax table used when in single quotes */\n", cfile); fputs("\n/* syntax table used when in single quotes */\n", cfile);
add("\n", "CNL"); add("\n", "CNL");
add("'", "CENDQUOTE"); add("'", "CENDQUOTE");
add("!*?[=", "CCTL"); /* ':/' for tilde expansion, '-' for [a\-x] pattern ranges */
add("!*?[=~:/-", "CCTL");
print("sqsyntax"); 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"); filltable("0");
fputs("\n/* character classification table */\n", cfile); fputs("\n/* character classification table */\n", cfile);
add("0123456789", "ISDIGIT"); add("0123456789", "ISDIGIT");
@ -231,8 +264,8 @@ main() {
* Clear the syntax table. * Clear the syntax table.
*/ */
filltable(dftval) static void
char *dftval; filltable(char *dftval)
{ {
int i; int i;
@ -245,7 +278,9 @@ filltable(dftval)
* Initialize the syntax table with default values. * Initialize the syntax table with default values.
*/ */
init() { static void
init(void)
{
filltable("CWORD"); filltable("CWORD");
syntax[0] = "CEOF"; syntax[0] = "CEOF";
syntax[base + CTLESC] = "CCTL"; syntax[base + CTLESC] = "CCTL";
@ -253,6 +288,9 @@ init() {
syntax[base + CTLENDVAR] = "CCTL"; syntax[base + CTLENDVAR] = "CCTL";
syntax[base + CTLBACKQ] = "CCTL"; syntax[base + CTLBACKQ] = "CCTL";
syntax[base + CTLBACKQ + CTLQUOTE] = "CCTL"; syntax[base + CTLBACKQ + CTLQUOTE] = "CCTL";
syntax[base + CTLARI] = "CCTL";
syntax[base + CTLENDARI] = "CCTL";
syntax[base + CTLQUOTEMARK] = "CCTL";
} }
@ -260,8 +298,8 @@ init() {
* Add entries to the syntax table. * Add entries to the syntax table.
*/ */
add(p, type) static void
char *p, *type; add(char *p, char *type)
{ {
while (*p) while (*p)
syntax[*p++ + base] = type; syntax[*p++ + base] = type;
@ -273,8 +311,8 @@ add(p, type)
* Output the syntax table. * Output the syntax table.
*/ */
print(name) static void
char *name; print(char *name)
{ {
int i; int i;
int col; int col;
@ -306,16 +344,18 @@ print(name)
* contiguous, we can test for them quickly. * contiguous, we can test for them quickly.
*/ */
char *macro[] = { static char *macro[] = {
"#define is_digit(c)\t((is_type+SYNBASE)[c] & ISDIGIT)", "#define is_digit(c)\t((is_type+SYNBASE)[c] & ISDIGIT)",
"#define is_alpha(c)\t((is_type+SYNBASE)[c] & (ISUPPER|ISLOWER))", "#define is_alpha(c)\t((c) != PEOF && ((c) < CTLESC || (c) > CTLQUOTEMARK) && isalpha((unsigned char) (c)))",
"#define is_name(c)\t((is_type+SYNBASE)[c] & (ISUPPER|ISLOWER|ISUNDER))", "#define is_name(c)\t((c) != PEOF && ((c) < CTLESC || (c) > CTLQUOTEMARK) && ((c) == '_' || isalpha((unsigned char) (c))))",
"#define is_in_name(c)\t((is_type+SYNBASE)[c] & (ISUPPER|ISLOWER|ISUNDER|ISDIGIT))", "#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))", "#define is_special(c)\t((is_type+SYNBASE)[c] & (ISSPECL|ISDIGIT))",
NULL NULL
}; };
output_type_macros() { static void
output_type_macros(void)
{
char **pp; char **pp;
if (digit_contig) if (digit_contig)
@ -334,7 +374,9 @@ output_type_macros() {
* Output digit conversion table (if digits are not contiguous). * Output digit conversion table (if digits are not contiguous).
*/ */
digit_convert() { static void
digit_convert(void)
{
int maxdigit; int maxdigit;
static char digit[] = "0123456789"; static char digit[] = "0123456789";
char *p; char *p;
@ -350,7 +392,11 @@ digit_convert() {
for (p = digit ; *p && *p != i ; p++); for (p = digit ; *p && *p != i ; p++);
if (*p == '\0') if (*p == '\0')
p = digit; p = digit;
fprintf(cfile, " %d,\n", p - digit); fprintf(cfile, " %d,\n", (int)(p - digit));
} }
fputs("};\n", cfile); fputs("};\n", cfile);
} }
/*
* $PchId: mksyntax.c,v 1.7 2006/05/23 12:04:27 philip Exp $
*/

View file

@ -1,7 +1,7 @@
#!/bin/sh - #!/bin/sh -
# #
# Copyright (c) 1991 The Regents of the University of California. # Copyright (c) 1991, 1993
# All rights reserved. # The Regents of the University of California. All rights reserved.
# #
# This code is derived from software contributed to Berkeley by # This code is derived from software contributed to Berkeley by
# Kenneth Almquist. # Kenneth Almquist.
@ -14,10 +14,6 @@
# 2. Redistributions in binary form must reproduce the above copyright # 2. Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the # notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution. # 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 # 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 # may be used to endorse or promote products derived from this software
# without specific prior written permission. # without specific prior written permission.
@ -34,7 +30,8 @@
# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF # OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
# SUCH DAMAGE. # 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) # 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 # token marks the end of a list. The third column is the name to print in
# error messages. # error messages.
cat > /tmp/ka$$ <<\! #temp=`/usr/bin/mktemp -t ka`
temp=/tmp/mkt$$
cat > $temp <<\!
TEOF 1 end of file TEOF 1 end of file
TNL 0 newline TNL 0 newline
TSEMI 0 ";" TSEMI 0 ";"
@ -70,16 +69,17 @@ TBEGIN 0 "{"
TEND 1 "}" TEND 1 "}"
TCASE 0 "case" TCASE 0 "case"
TESAC 1 "esac" TESAC 1 "esac"
TNOT 0 "!"
! !
nl=`wc -l /tmp/ka$$` nl=`wc -l $temp`
exec > token.def exec > token.h
i=0 i=0
while read line while read line
do do
set -$- $line set -$- $line
echo "#define $1 $i" echo "#define $1 $i"
i=`expr $i + 1` i=`expr $i + 1`
done </tmp/ka$$ done <$temp
echo ' echo '
/* Array indicating which tokens mark the end of a list */ /* Array indicating which tokens mark the end of a list */
const char tokendlist[] = {' const char tokendlist[] = {'
@ -87,18 +87,18 @@ while read line
do do
set -$- $line set -$- $line
echo " $2," echo " $2,"
done </tmp/ka$$ done <$temp
echo '}; echo '};
char *const tokname[] = {' const char *const tokname[] = {'
sed -e 's/"/\\"/g' \ sed -e 's/"/\\"/g' \
-e 's/[^ ]*[ ][ ]*[^ ]*[ ][ ]*\(.*\)/ "\1",/' \ -e 's/[^ ]*[ ][ ]*[^ ]*[ ][ ]*\(.*\)/ "\1",/' \
/tmp/ka$$ $temp
echo '}; echo '};
' '
i=0 i=0
go= go=
sed 's/"//g' /tmp/ka$$ | sed 's/"//g' $temp |
while read line while read line
do do
set -$- $line set -$- $line
@ -106,7 +106,7 @@ sed 's/"//g' /tmp/ka$$ |
then then
echo "#define KWDOFFSET $i" echo "#define KWDOFFSET $i"
echo echo
echo "char *const parsekwd[] = {" echo "const char *const parsekwd[] = {"
go=true go=true
fi fi
if [ "$go" ] if [ "$go" ]
@ -118,4 +118,7 @@ sed 's/"//g' /tmp/ka$$ |
echo ' 0 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
View 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 $
*/

View file

@ -1,6 +1,6 @@
/*- /*-
* Copyright (c) 1991 The Regents of the University of California. * Copyright (c) 1991, 1993
* All rights reserved. * The Regents of the University of California. All rights reserved.
* *
* This code is derived from software contributed to Berkeley by * This code is derived from software contributed to Berkeley by
* Kenneth Almquist. * Kenneth Almquist.
@ -13,10 +13,6 @@
* 2. Redistributions in binary form must reproduce the above copyright * 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the * notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution. * 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 * 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 * may be used to endorse or promote products derived from this software
* without specific prior written permission. * without specific prior written permission.
@ -35,8 +31,14 @@
*/ */
#ifndef lint #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 */ #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. * 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. * equal(s1, s2) Return true if strings are equal.
* scopy(from, to) Copy a string. * scopy(from, to) Copy a string.
* scopyn(from, to, n) Like scopy, but checks for overflow. * 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. * number(s) Convert a string of digits to an integer.
* is_number(s) Return true if s is a string of digits. * is_number(s) Return true if s is a string of digits.
*/ */
#include <stdlib.h>
#include "shell.h" #include "shell.h"
#include "syntax.h" #include "syntax.h"
#include "error.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 */ 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 * scopyn - copy a string from "from" to "to", truncating the string
@ -66,10 +75,7 @@ char nullstr[1]; /* zero length string */
*/ */
void void
scopyn(from, to, size) scopyn(const char *from, char *to, int size)
register char const *from;
register char *to;
register int size;
{ {
while (--size > 0) { while (--size > 0) {
@ -80,58 +86,12 @@ 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. * prefix -- see if pfx is a prefix of string.
*/ */
int int
prefix(pfx, string) prefix(const char *pfx, const char *string)
register char const *pfx;
register char const *string;
{ {
while (*pfx) { while (*pfx) {
if (*pfx++ != *string++) if (*pfx++ != *string++)
@ -147,12 +107,10 @@ prefix(pfx, string)
*/ */
int int
number(s) number(const char *s)
const char *s;
{ {
if (! is_number(s)) if (! is_number(s))
error2("Illegal number", (char *)s); error("Illegal number: %s", (char *)s);
return atoi(s); return atoi(s);
} }
@ -163,8 +121,7 @@ number(s)
*/ */
int int
is_number(p) is_number(const char *p)
register const char *p;
{ {
do { do {
if (! is_digit(*p)) if (! is_digit(*p))
@ -172,3 +129,7 @@ is_number(p)
} while (*++p != '\0'); } while (*++p != '\0');
return 1; return 1;
} }
/*
* $PchId: mystring.c,v 1.4 2006/05/22 12:21:53 philip Exp $
*/

View file

@ -1,6 +1,6 @@
/*- /*-
* Copyright (c) 1991 The Regents of the University of California. * Copyright (c) 1991, 1993
* All rights reserved. * The Regents of the University of California. All rights reserved.
* *
* This code is derived from software contributed to Berkeley by * This code is derived from software contributed to Berkeley by
* Kenneth Almquist. * Kenneth Almquist.
@ -13,10 +13,6 @@
* 2. Redistributions in binary form must reproduce the above copyright * 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the * notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution. * 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 * 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 * may be used to endorse or promote products derived from this software
* without specific prior written permission. * without specific prior written permission.
@ -33,39 +29,20 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE. * 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 #include <string.h>
#define strchr mystrchr
#endif
#ifdef __STDC__
void scopyn(const char *, char *, int); void scopyn(const char *, char *, int);
char *strchr(const char *, int);
void mybcopy(const pointer, pointer, int);
int prefix(const char *, const char *); int prefix(const char *, const char *);
int number(const char *); int number(const char *);
int is_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 equal(s1, s2) (strcmp(s1, s2) == 0)
#define scopy(s1, s2) ((void)strcpy(s2, s1)) #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 $
*/

View file

@ -1,6 +1,6 @@
/*- /*-
* Copyright (c) 1991 The Regents of the University of California. * Copyright (c) 1991, 1993
* All rights reserved. * The Regents of the University of California. All rights reserved.
* *
* This code is derived from software contributed to Berkeley by * This code is derived from software contributed to Berkeley by
* Kenneth Almquist. * Kenneth Almquist.
@ -13,10 +13,6 @@
* 2. Redistributions in binary form must reproduce the above copyright * 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the * notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution. * 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 * 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 * may be used to endorse or promote products derived from this software
* without specific prior written permission. * without specific prior written permission.
@ -33,9 +29,11 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE. * 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. * Routine for dealing with parsed shell commands.
*/ */
@ -43,35 +41,26 @@
#include "shell.h" #include "shell.h"
#include "nodes.h" #include "nodes.h"
#include "memalloc.h" #include "memalloc.h"
#include "machdep.h"
#include "mystring.h" #include "mystring.h"
#ifndef __minix
int funcblocksize; /* size of structures in function */ #include <sys/param.h>
int funcstringsize; /* size of strings in node */
#ifdef __STDC__
pointer funcblock; /* block to allocate function from */
#else
char *funcblock; /* block to allocate function from */
#endif #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 %SIZES
#ifdef __STDC__
STATIC void calcsize(union node *); STATIC void calcsize(union node *);
STATIC void sizenodelist(struct nodelist *); STATIC void sizenodelist(struct nodelist *);
STATIC union node *copynode(union node *); STATIC union node *copynode(union node *);
STATIC struct nodelist *copynodelist(struct nodelist *); STATIC struct nodelist *copynodelist(struct nodelist *);
STATIC char *nodesavestr(char *); STATIC char *nodesavestr(char *);
#else
STATIC void calcsize();
STATIC void sizenodelist();
STATIC union node *copynode();
STATIC struct nodelist *copynodelist();
STATIC char *nodesavestr();
#endif
@ -80,8 +69,7 @@ STATIC char *nodesavestr();
*/ */
union node * union node *
copyfunc(n) copyfunc(union node *n)
union node *n;
{ {
if (n == NULL) if (n == NULL)
return NULL; return NULL;
@ -96,8 +84,7 @@ copyfunc(n)
STATIC void STATIC void
calcsize(n) calcsize(union node *n)
union node *n;
{ {
%CALCSIZE %CALCSIZE
} }
@ -105,8 +92,7 @@ calcsize(n)
STATIC void STATIC void
sizenodelist(lp) sizenodelist(struct nodelist *lp)
struct nodelist *lp;
{ {
while (lp) { while (lp) {
funcblocksize += ALIGN(sizeof(struct nodelist)); funcblocksize += ALIGN(sizeof(struct nodelist));
@ -118,8 +104,7 @@ sizenodelist(lp)
STATIC union node * STATIC union node *
copynode(n) copynode(union node *n)
union node *n;
{ {
union node *new; union node *new;
@ -129,8 +114,7 @@ copynode(n)
STATIC struct nodelist * STATIC struct nodelist *
copynodelist(lp) copynodelist(struct nodelist *lp)
struct nodelist *lp;
{ {
struct nodelist *start; struct nodelist *start;
struct nodelist **lpp; struct nodelist **lpp;
@ -138,7 +122,7 @@ copynodelist(lp)
lpp = &start; lpp = &start;
while (lp) { while (lp) {
*lpp = funcblock; *lpp = funcblock;
*(char **)&funcblock += ALIGN(sizeof (struct nodelist)); funcblock = (char *)funcblock + ALIGN(sizeof(struct nodelist));
(*lpp)->n = copynode(lp->n); (*lpp)->n = copynode(lp->n);
lp = lp->next; lp = lp->next;
lpp = &(*lpp)->next; lpp = &(*lpp)->next;
@ -150,14 +134,14 @@ copynodelist(lp)
STATIC char * STATIC char *
nodesavestr(s) nodesavestr(char *s)
char *s;
{ {
register char *p = s; char *p = s;
register char *q = funcstring; char *q = funcstring;
char *rtn = funcstring; char *rtn = funcstring;
while (*q++ = *p++); while ((*q++ = *p++) != '\0')
continue;
funcstring = q; funcstring = q;
return rtn; return rtn;
} }
@ -169,9 +153,12 @@ nodesavestr(s)
*/ */
void void
freefunc(n) freefunc(union node *n)
union node *n;
{ {
if (n) if (n)
ckfree(n); ckfree(n);
} }
/*
* $PchId: nodes.c.pat,v 1.5 2006/05/22 12:43:57 philip Exp $
*/

View file

@ -1,7 +1,6 @@
#!/bin/sh -
# #
# Copyright (c) 1991 The Regents of the University of California. # Copyright (c) 1991, 1993
# All rights reserved. # The Regents of the University of California. All rights reserved.
# #
# This code is derived from software contributed to Berkeley by # This code is derived from software contributed to Berkeley by
# Kenneth Almquist. # Kenneth Almquist.
@ -14,10 +13,6 @@
# 2. Redistributions in binary form must reproduce the above copyright # 2. Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the # notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution. # 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 # 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 # may be used to endorse or promote products derived from this software
# without specific prior written permission. # without specific prior written permission.
@ -34,7 +29,8 @@
# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF # OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
# SUCH DAMAGE. # 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 # This file describes the nodes used in parse trees. Unindented lines
# contain a node type followed by a structure tag. Subsequent indented # contain a node type followed by a structure tag. Subsequent indented
@ -118,7 +114,9 @@ NARG narg # represents a word
NTO nfile # fd> fname NTO nfile # fd> fname
NFROM nfile # fd< fname NFROM nfile # fd< fname
NFROMTO nfile # fd<> fname
NAPPEND nfile # fd>> fname NAPPEND nfile # fd>> fname
NCLOBBER nfile # fd>| fname
type int type int
next nodeptr # next redirection in list next nodeptr # next redirection in list
fd int # file descriptor being redirected fd int # file descriptor being redirected
@ -131,6 +129,8 @@ NFROMFD ndup # fd>&dupfd
next nodeptr # next redirection in list next nodeptr # next redirection in list
fd int # file descriptor being redirected fd int # file descriptor being redirected
dupfd int # file descriptor to duplicate dupfd int # file descriptor to duplicate
vname nodeptr # file name if fd>&$var
NHERE nhere # fd<<\! NHERE nhere # fd<<\!
NXHERE nhere # fd<<! NXHERE nhere # fd<<!
@ -138,3 +138,10 @@ NXHERE nhere # fd<<!
next nodeptr # next redirection in list next nodeptr # next redirection in list
fd int # file descriptor being redirected fd int # file descriptor being redirected
doc nodeptr # input to command (NARG node) 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 $

View file

@ -1,6 +1,6 @@
/*- /*-
* Copyright (c) 1991 The Regents of the University of California. * Copyright (c) 1991, 1993
* All rights reserved. * The Regents of the University of California. All rights reserved.
* *
* This code is derived from software contributed to Berkeley by * This code is derived from software contributed to Berkeley by
* Kenneth Almquist. * Kenneth Almquist.
@ -13,10 +13,6 @@
* 2. Redistributions in binary form must reproduce the above copyright * 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the * notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution. * 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 * 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 * may be used to endorse or promote products derived from this software
* without specific prior written permission. * without specific prior written permission.
@ -35,8 +31,18 @@
*/ */
#ifndef lint #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 */ #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" #include "shell.h"
#define DEFINE_OPTIONS #define DEFINE_OPTIONS
@ -52,25 +58,24 @@ static char sccsid[] = "@(#)options.c 5.2 (Berkeley) 3/13/91";
#include "memalloc.h" #include "memalloc.h"
#include "error.h" #include "error.h"
#include "mystring.h" #include "mystring.h"
#include "builtins.h"
#if !defined(NO_HISTORY) && !defined(EDITLINE)
#include "myhistedit.h"
#endif
char *arg0; /* value of $0 */ char *arg0; /* value of $0 */
struct shparam shellparam; /* current positional parameters */ struct shparam shellparam; /* current positional parameters */
char **argptr; /* argument list for builtin commands */ 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 */ char *optptr; /* used by nextopt */
int editable; /* isatty(0) && isatty(1) */
char *minusc; /* argument to -c option */ char *minusc; /* argument to -c option */
#ifdef __STDC__
STATIC void options(int); STATIC void options(int);
STATIC void minus_o(char *, int);
STATIC void setoption(int, int); STATIC void setoption(int, int);
#else STATIC int getopts(char *, char *, char **, char ***, char **);
STATIC void options();
STATIC void setoption();
#endif
/* /*
@ -78,46 +83,55 @@ STATIC void setoption();
*/ */
void void
procargs(argc, argv) procargs(int argc, char **argv)
char **argv;
{ {
char *p; int i;
argptr = argv; argptr = argv;
if (argc > 0) if (argc > 0)
argptr++; argptr++;
for (p = optval ; p < optval + sizeof optval - 1 ; p++) for (i = 0; i < NOPTS; i++)
*p = 2; optlist[i].val = 2;
privileged = (getuid() != geteuid() || getgid() != getegid());
options(1); options(1);
if (*argptr == NULL && minusc == NULL) if (*argptr == NULL && minusc == NULL)
sflag = 1; sflag = 1;
editable = (isatty(0) && isatty(1)); if (iflag == 2 && sflag == 1 && isatty(0) && isatty(1))
if (iflag == 2 && sflag == 1 && editable)
iflag = 1; iflag = 1;
if (jflag == 2) if (mflag == 2)
jflag = iflag; mflag = iflag;
for (p = optval ; p < optval + sizeof optval - 1 ; p++) for (i = 0; i < NOPTS; i++)
if (*p == 2) if (optlist[i].val == 2)
*p = 0; optlist[i].val = 0;
arg0 = argv[0]; arg0 = argv[0];
if (sflag == 0) { if (sflag == 0 && minusc == NULL) {
arg0 = *argptr++; commandname = arg0 = *argptr++;
if (minusc == NULL) {
commandname = arg0;
setinputfile(commandname, 0); 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.p = argptr;
shellparam.reset = 1;
/* assert(shellparam.malloc == 0 && shellparam.nparam == 0); */ /* assert(shellparam.malloc == 0 && shellparam.nparam == 0); */
while (*argptr) { while (*argptr) {
shellparam.nparam++; shellparam.nparam++;
argptr++; argptr++;
} }
setinteractive(iflag); optschanged();
setjobctl(jflag);
} }
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 * Process shell options. The global variable argptr contains a pointer
@ -125,8 +139,9 @@ procargs(argc, argv)
*/ */
STATIC void STATIC void
options(cmdline) { options(int cmdline)
register char *p; {
char *p;
int val; int val;
int c; int c;
@ -136,7 +151,7 @@ options(cmdline) {
argptr++; argptr++;
if ((c = *p++) == '-') { if ((c = *p++) == '-') {
val = 1; val = 1;
if (p[0] == '\0' || p[0] == '-' && p[1] == '\0') { if (p[0] == '\0' || (p[0] == '-' && p[1] == '\0')) {
if (!cmdline) { if (!cmdline) {
/* "-" means turn off -x and -v */ /* "-" means turn off -x and -v */
if (p[0] == '\0') if (p[0] == '\0')
@ -166,26 +181,79 @@ options(cmdline) {
#ifdef NOHACK #ifdef NOHACK
break; break;
#endif #endif
} else if (c == 'o') {
minus_o(*argptr, val);
if (*argptr)
argptr++;
} else { } else {
if (c == 'p' && !val && privileged) {
(void) setuid(getuid());
(void) setgid(getgid());
}
setoption(c, val); 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 STATIC void
setoption(flag, val) setoption(int flag, int val)
char flag;
int val;
{ {
register char *p; int i;
if ((p = strchr(optchar, flag)) == NULL) 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); error("Illegal option -%c", flag);
optval[p - optchar] = val;
} }
@ -194,10 +262,12 @@ setoption(flag, val)
INCLUDE "options.h" INCLUDE "options.h"
SHELLPROC { 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 #endif
@ -207,8 +277,7 @@ SHELLPROC {
*/ */
void void
setparam(argv) setparam(char **argv)
char **argv;
{ {
char **newparam; char **newparam;
char **ap; char **ap;
@ -233,8 +302,7 @@ setparam(argv)
*/ */
void void
freeparam(param) freeparam(struct shparam *param)
struct shparam *param;
{ {
char **ap; char **ap;
@ -251,7 +319,9 @@ freeparam(param)
* The shift builtin command. * The shift builtin command.
*/ */
shiftcmd(argc, argv) char **argv; { int
shiftcmd(int argc, char **argv)
{
int n; int n;
char **ap1, **ap2; char **ap1, **ap2;
@ -259,7 +329,7 @@ shiftcmd(argc, argv) char **argv; {
if (argc > 1) if (argc > 1)
n = number(argv[1]); n = number(argv[1]);
if (n > shellparam.nparam) if (n > shellparam.nparam)
n = shellparam.nparam; error("can't shift that many");
INTOFF; INTOFF;
shellparam.nparam -= n; shellparam.nparam -= n;
for (ap1 = shellparam.p ; --n >= 0 ; ap1++) { for (ap1 = shellparam.p ; --n >= 0 ; ap1++) {
@ -279,13 +349,14 @@ shiftcmd(argc, argv) char **argv; {
* The set command builtin. * The set command builtin.
*/ */
setcmd(argc, argv) char **argv; { int
setcmd(int argc, char **argv)
{
if (argc == 1) if (argc == 1)
return showvarscmd(argc, argv); return showvarscmd(argc, argv);
INTOFF; INTOFF;
options(0); options(0);
setinteractive(iflag); optschanged();
setjobctl(jflag);
if (*argptr != NULL) { if (*argptr != NULL) {
setparam(argptr); 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 * The getopts builtin. Shellparam.optnext points to the next argument
* to be processed. Shellparam.optptr points to the next character to * 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. * then it's the first time getopts has been called.
*/ */
getoptscmd(argc, argv) char **argv; { int
register char *p, *q; getoptscmd(int argc, char **argv)
char c; {
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]; char s[10];
if (argc != 3) if ((p = *optptr) == NULL || *p == '\0') {
error("Usage: getopts optstring var"); /* Current word is done, advance */
if (shellparam.optnext == NULL) { if (*optnext == NULL)
shellparam.optnext = shellparam.p; return 1;
shellparam.optptr = NULL; p = **optnext;
}
if ((p = shellparam.optptr) == NULL || *p == '\0') {
p = *shellparam.optnext;
if (p == NULL || *p != '-' || *++p == '\0') { if (p == NULL || *p != '-' || *++p == '\0') {
atend: atend:
fmtstr(s, 10, "%d", shellparam.optnext - shellparam.p + 1); ind = *optnext - optfirst + 1;
setvar("OPTIND", s, 0); *optnext = NULL;
shellparam.optnext = NULL; p = NULL;
return 1; done = 1;
goto out;
} }
shellparam.optnext++; (*optnext)++;
if (p[0] == '-' && p[1] == '\0') /* check for "--" */ if (p[0] == '-' && p[1] == '\0') /* check for "--" */
goto atend; goto atend;
} }
c = *p++; c = *p++;
for (q = argv[1] ; *q != c ; ) { for (q = optstr; *q != c; ) {
if (*q == '\0') { if (*q == '\0') {
if (optstr[0] == ':') {
s[0] = c;
s[1] = '\0';
err |= setvarsafe("OPTARG", s, 0);
}
else {
out1fmt("Illegal option -%c\n", c); out1fmt("Illegal option -%c\n", c);
(void) unsetvar("OPTARG");
}
c = '?'; c = '?';
goto out; goto bad;
} }
if (*++q == ':') if (*++q == ':')
q++; q++;
} }
if (*++q == ':') { if (*++q == ':') {
if (*p == '\0') { if (*p == '\0' && (p = **optnext) == NULL) {
if ((p = *shellparam.optnext) == NULL) { if (optstr[0] == ':') {
out1fmt("No arg for -%c option\n", c);
c = '?';
goto out;
}
shellparam.optnext++;
}
setvar("OPTARG", p, 0);
p = "";
}
out:
shellparam.optptr = p;
s[0] = c; s[0] = c;
s[1] = '\0'; s[1] = '\0';
setvar(argv[2], s, 0); err |= setvarsafe("OPTARG", s, 0);
fmtstr(s, 10, "%d", shellparam.optnext - shellparam.p + 1); c = ':';
setvar("OPTIND", s, 0); }
return 0; else {
out1fmt("No arg for -%c option\n", c);
(void) unsetvar("OPTARG");
c = '?';
}
goto bad;
}
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:
*optptr = p;
fmtstr(s, sizeof(s), "%d", ind);
err |= setvarsafe("OPTIND", s, VNOFUNC);
s[0] = c;
s[1] = '\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 * Standard option processing (a la getopt) for builtin routines. The
* only argument that is passed to nextopt is the option string; the * only argument that is passed to nextopt is the option string; the
* other arguments are unnecessary. It return the character, or '\0' on * other arguments are unnecessary. It return the character, or '\0' on
@ -365,10 +509,9 @@ out:
*/ */
int int
nextopt(optstring) nextopt(char *optstring)
char *optstring;
{ {
register char *p, *q; char *p, *q;
char c; char c;
if ((p = optptr) == NULL || *p == '\0') { if ((p = optptr) == NULL || *p == '\0') {
@ -389,9 +532,13 @@ nextopt(optstring)
if (*++q == ':') { if (*++q == ':') {
if (*p == '\0' && (p = *argptr++) == NULL) if (*p == '\0' && (p = *argptr++) == NULL)
error("No arg for -%c option", c); error("No arg for -%c option", c);
optarg = p; shoptarg = p;
p = NULL; p = NULL;
} }
optptr = p; optptr = p;
return c; return c;
} }
/*
* $PchId: options.c,v 1.5 2006/05/22 12:23:10 philip Exp $
*/

View file

@ -1,6 +1,6 @@
/*- /*-
* Copyright (c) 1991 The Regents of the University of California. * Copyright (c) 1991, 1993
* All rights reserved. * The Regents of the University of California. All rights reserved.
* *
* This code is derived from software contributed to Berkeley by * This code is derived from software contributed to Berkeley by
* Kenneth Almquist. * Kenneth Almquist.
@ -13,10 +13,6 @@
* 2. Redistributions in binary form must reproduce the above copyright * 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the * notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution. * 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 * 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 * may be used to endorse or promote products derived from this software
* without specific prior written permission. * without specific prior written permission.
@ -33,12 +29,14 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE. * 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 { struct shparam {
int nparam; /* number of positional parameters (without $0) */ int nparam; /* # of positional parameters (without $0) */
char malloc; /* true if parameter list dynamicly allocated */ unsigned char malloc; /* if parameter list dynamically allocated */
unsigned char reset; /* if getopts has been reset */
char **p; /* parameter list */ char **p; /* parameter list */
char **optnext; /* next parameter to be processed by getopts */ char **optnext; /* next parameter to be processed by getopts */
char *optptr; /* used by getopts */ char *optptr; /* used by getopts */
@ -46,25 +44,56 @@ struct shparam {
#define eflag optval[0] #define eflag optlist[0].val
#define fflag optval[1] #define fflag optlist[1].val
#define Iflag optval[2] #define Iflag optlist[2].val
#define iflag optval[3] #define iflag optlist[3].val
#define jflag optval[4] #define mflag optlist[4].val
#define nflag optval[5] #define nflag optlist[5].val
#define sflag optval[6] #define sflag optlist[6].val
#define xflag optval[7] #define xflag optlist[7].val
#define zflag optval[8] #define vflag optlist[8].val
#define vflag optval[9] #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 #ifdef DEFINE_OPTIONS
const char optchar[NOPTS+1] = "efIijnsxzv"; /* shell flags */ struct optent optlist[NOPTS] = {
char optval[NOPTS+1]; /* values of option flags */ { "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 #else
extern const char optchar[NOPTS+1]; extern struct optent optlist[NOPTS];
extern char optval[NOPTS+1];
#endif #endif
@ -72,19 +101,19 @@ extern char *minusc; /* argument to -c option */
extern char *arg0; /* $0 */ extern char *arg0; /* $0 */
extern struct shparam shellparam; /* $@ */ extern struct shparam shellparam; /* $@ */
extern char **argptr; /* argument list for builtin commands */ 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 char *optptr; /* used by nextopt */
extern int editable; /* isatty(0) && isatty(1) */
#ifdef __STDC__
void procargs(int, char **); void procargs(int, char **);
void optschanged(void);
void setparam(char **); void setparam(char **);
void freeparam(struct shparam *); void freeparam(struct shparam *);
int shiftcmd(int, char **);
int setcmd(int, char **);
int getoptscmd(int, char **);
int nextopt(char *); int nextopt(char *);
#else void getoptsreset(const char *);
void procargs();
void setparam(); /*
void freeparam(); * $PchId: options.h,v 1.4 2006/03/29 15:37:43 philip Exp $
int nextopt(); */
#endif

View file

@ -1,6 +1,6 @@
/*- /*-
* Copyright (c) 1991 The Regents of the University of California. * Copyright (c) 1991, 1993
* All rights reserved. * The Regents of the University of California. All rights reserved.
* *
* This code is derived from software contributed to Berkeley by * This code is derived from software contributed to Berkeley by
* Kenneth Almquist. * Kenneth Almquist.
@ -13,10 +13,6 @@
* 2. Redistributions in binary form must reproduce the above copyright * 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the * notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution. * 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 * 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 * may be used to endorse or promote products derived from this software
* without specific prior written permission. * without specific prior written permission.
@ -35,7 +31,7 @@
*/ */
#ifndef lint #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 */ #endif /* not lint */
/* /*
@ -55,12 +51,16 @@ static char sccsid[] = "@(#)output.c 5.1 (Berkeley) 3/7/91";
#include "output.h" #include "output.h"
#include "memalloc.h" #include "memalloc.h"
#include "error.h" #include "error.h"
#include "var.h"
#ifdef __STDC__ #ifdef __STDC__
#include "stdarg.h" #include "stdarg.h"
#else #else
#include <varargs.h> #include <varargs.h>
#endif #endif
#include <errno.h> #include <errno.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#define OUTBUFSIZ BUFSIZ #define OUTBUFSIZ BUFSIZ
@ -115,15 +115,20 @@ open_mem(block, length, file)
void void
out1str(p) out1str(p)
char *p; const char *p;
{ {
outstr(p, out1); outstr(p, out1);
} }
void
out1qstr(const char *p)
{
outqstr(p, out1);
}
void void
out2str(p) out2str(const char *p)
char *p;
{ {
outstr(p, out2); outstr(p, out2);
} }
@ -131,11 +136,42 @@ out2str(p)
void void
outstr(p, file) outstr(p, file)
register char *p; register const char *p;
register struct output *file; register struct output *file;
{ {
while (*p) while (*p)
outc(*p++, file); 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__ #ifdef __STDC__
void void
outfmt(struct output *file, char *fmt, ...) { outfmt(struct output *file, const char *fmt, ...)
{
va_list ap; va_list ap;
va_start(ap, fmt); va_start(ap, fmt);
@ -218,7 +255,8 @@ outfmt(struct output *file, char *fmt, ...) {
void void
out1fmt(char *fmt, ...) { out1fmt(const char *fmt, ...)
{
va_list ap; va_list ap;
va_start(ap, fmt); va_start(ap, fmt);
@ -226,9 +264,20 @@ out1fmt(char *fmt, ...) {
va_end(ap); 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 void
fmtstr(char *outbuf, int length, char *fmt, ...) { fmtstr(char *outbuf, int length, const char *fmt, ...)
{
va_list ap; va_list ap;
struct output strout; struct output strout;
@ -275,6 +324,19 @@ out1fmt(va_alist)
va_end(ap); 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 void
fmtstr(va_alist) fmtstr(va_alist)
@ -325,10 +387,7 @@ static const char digit[17] = "0123456789ABCDEF";
void void
doformat(dest, f, ap) doformat(struct output *dest, const char *f, va_list ap)
register struct output *dest;
register char *f; /* format string */
va_list ap;
{ {
register char c; register char c;
char temp[TEMPSIZE]; char temp[TEMPSIZE];
@ -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;
}

View file

@ -1,6 +1,6 @@
/*- /*-
* Copyright (c) 1991 The Regents of the University of California. * Copyright (c) 1991, 1993
* All rights reserved. * The Regents of the University of California. All rights reserved.
* *
* This code is derived from software contributed to Berkeley by * This code is derived from software contributed to Berkeley by
* Kenneth Almquist. * Kenneth Almquist.
@ -13,10 +13,6 @@
* 2. Redistributions in binary form must reproduce the above copyright * 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the * notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution. * 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 * 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 * may be used to endorse or promote products derived from this software
* without specific prior written permission. * without specific prior written permission.
@ -33,11 +29,14 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE. * 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 #ifndef OUTPUT_INCL
#include <stdarg.h>
struct output { struct output {
char *nextc; char *nextc;
int nleft; int nleft;
@ -53,38 +52,27 @@ extern struct output memout;
extern struct output *out1; extern struct output *out1;
extern struct output *out2; extern struct output *out2;
#ifndef __printflike
#define __printflike(a,b)
#endif
#ifdef __STDC__ void open_mem(char *, int, struct output *);
void outstr(char *, struct output *); void out1str(const char *);
void out1str(char *); void out1qstr(const char *);
void out2str(char *); void out2str(const char *);
void outfmt(struct output *, char *, ...); void out2qstr(const char *);
void out1fmt(char *, ...); void outstr(const char *, struct output *);
void fmtstr(char *, int, char *, ...); void outqstr(const char *, struct output *);
/* void doformat(struct output *, char *, va_list); */
void doformat();
void emptyoutbuf(struct output *); void emptyoutbuf(struct output *);
void flushall(void); void flushall(void);
void flushout(struct output *); void flushout(struct output *);
void freestdout(void); 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 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 outc(c, file) (--(file)->nleft < 0? (emptyoutbuf(file), *(file)->nextc++ = (c)) : (*(file)->nextc++ = (c)))
#define out1c(c) outc(c, out1); #define out1c(c) outc(c, out1);
@ -92,3 +80,7 @@ int xioctl();
#define OUTPUT_INCL #define OUTPUT_INCL
#endif #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

View file

@ -1,6 +1,6 @@
/*- /*-
* Copyright (c) 1991 The Regents of the University of California. * Copyright (c) 1991, 1993
* All rights reserved. * The Regents of the University of California. All rights reserved.
* *
* This code is derived from software contributed to Berkeley by * This code is derived from software contributed to Berkeley by
* Kenneth Almquist. * Kenneth Almquist.
@ -13,10 +13,6 @@
* 2. Redistributions in binary form must reproduce the above copyright * 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the * notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution. * 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 * 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 * may be used to endorse or promote products derived from this software
* without specific prior written permission. * without specific prior written permission.
@ -33,7 +29,8 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE. * 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 */ /* control characters in argument strings */
@ -42,18 +39,27 @@
#define CTLENDVAR '\203' #define CTLENDVAR '\203'
#define CTLBACKQ '\204' #define CTLBACKQ '\204'
#define CTLQUOTE 01 /* ored with CTLBACKQ code if in quotes */ #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) */ /* variable substitution byte (follows CTLVAR) */
#define VSTYPE 07 /* type of variable substitution */ #define VSTYPE 0x0f /* type of variable substitution */
#define VSNUL 040 /* colon--treat the empty string as unset */ #define VSNUL 0x10 /* colon--treat the empty string as unset */
#define VSQUOTE 0100 /* inside double quotes--suppress splitting */ #define VSQUOTE 0x80 /* inside double quotes--suppress splitting */
/* values of VSTYPE field */ /* values of VSTYPE field */
#define VSNORMAL 1 /* normal variable: $var or ${var} */ #define VSNORMAL 0x1 /* normal variable: $var or ${var} */
#define VSMINUS 2 /* ${var-text} */ #define VSMINUS 0x2 /* ${var-text} */
#define VSPLUS 3 /* ${var+text} */ #define VSPLUS 0x3 /* ${var+text} */
#define VSQUESTION 4 /* ${var?message} */ #define VSQUESTION 0x4 /* ${var?message} */
#define VSASSIGN 5 /* ${var=text} */ #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; extern int tokpushback;
#define NEOF ((union node *)&tokpushback) #define NEOF ((union node *)&tokpushback)
extern int whichprompt; /* 1 == PS1, 2 == PS2 */
#ifdef __STDC__
union node *parsecmd(int); union node *parsecmd(int);
void fixredir(union node *, const char *, int);
int goodname(char *); int goodname(char *);
#else char *getprompt(void *);
union node *parsecmd();
int goodname(); /*
#endif * $PchId: parser.h,v 1.3 2006/03/29 14:33:35 philip Exp $
*/

View file

@ -1,6 +1,6 @@
/*- /*-
* Copyright (c) 1991 The Regents of the University of California. * Copyright (c) 1991, 1993
* All rights reserved. * The Regents of the University of California. All rights reserved.
* *
* This code is derived from software contributed to Berkeley by * This code is derived from software contributed to Berkeley by
* Kenneth Almquist. * Kenneth Almquist.
@ -13,10 +13,6 @@
* 2. Redistributions in binary form must reproduce the above copyright * 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the * notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution. * 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 * 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 * may be used to endorse or promote products derived from this software
* without specific prior written permission. * without specific prior written permission.
@ -35,8 +31,23 @@
*/ */
#ifndef lint #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 */ #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. * 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 "jobs.h"
#include "expand.h" #include "expand.h"
#include "redir.h" #include "redir.h"
#include "eval.h"
#include "output.h" #include "output.h"
#include "memalloc.h" #include "memalloc.h"
#include "error.h" #include "error.h"
#include <sys/types.h> #include "options.h"
#include <signal.h>
#include <fcntl.h>
#include <errno.h>
#include <limits.h>
#define EMPTY -2 /* marks an unused slot in redirtab */ #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 MKINIT
struct redirtab { struct redirtab {
struct redirtab *next; struct redirtab *next;
short renamed[10]; int renamed[10];
}; };
MKINIT struct redirtab *redirlist; 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 * We keep track of whether or not fd0 has been redirected. This is for
if it hasn't already been redirected. */ * background commands, where we want to redirect fd0 to /dev/null only
int fd0_redirected = 0; * if it hasn't already been redirected.
*/
STATIC int fd0_redirected = 0;
#ifdef __STDC__ STATIC void openredirect(union node *, char[10 ]);
STATIC void openredirect(union node *, char *);
STATIC int openhere(union node *); STATIC int openhere(union node *);
#else
STATIC void openredirect();
STATIC int openhere();
#endif
/* /*
@ -95,14 +97,13 @@ STATIC int openhere();
*/ */
void void
redirect(redir, flags) redirect(union node *redir, int flags)
union node *redir;
int flags;
{ {
union node *n; union node *n;
struct redirtab *sv; struct redirtab *sv = NULL;
int i; int i;
int fd; int fd;
int try;
char memory[10]; /* file descriptors to write to memory */ char memory[10]; /* file descriptors to write to memory */
for (i = 10 ; --i >= 0 ; ) for (i = 10 ; --i >= 0 ; )
@ -117,20 +118,37 @@ redirect(redir, flags)
} }
for (n = redir ; n ; n = n->nfile.next) { for (n = redir ; n ; n = n->nfile.next) {
fd = n->nfile.fd; 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) { if ((flags & REDIR_PUSH) && sv->renamed[fd] == EMPTY) {
INTOFF; 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; sv->renamed[fd] = i;
close(fd);
} }
INTON; INTON;
if (i == EMPTY)
error("Out of file descriptors");
} else {
close(fd);
} }
if (fd == 0) if (fd == 0)
fd0_redirected++; fd0_redirected++;
if (!try)
openredirect(n, memory); openredirect(n, memory);
} }
if (memory[1]) if (memory[1])
@ -141,16 +159,15 @@ redirect(redir, flags)
STATIC void STATIC void
openredirect(redir, memory) openredirect(union node *redir, char memory[10])
union node *redir;
char memory[10];
{ {
struct stat sb;
int fd = redir->nfile.fd; int fd = redir->nfile.fd;
char *fname; char *fname;
int f; int f;
/* Assume redirection succeeds. */ /* Assume redirection succeeds. */
exitstatus = 0; { extern int exitstatus; exitstatus = 0; }
/* /*
* We suppress interrupts so that we won't leave open file * We suppress interrupts so that we won't leave open file
@ -163,34 +180,35 @@ openredirect(redir, memory)
case NFROM: case NFROM:
fname = redir->nfile.expfname; fname = redir->nfile.expfname;
if ((f = open(fname, O_RDONLY)) < 0) 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: movefd:
if (f != fd) { if (f != fd) {
copyfd(f, fd); dup2(f, fd);
close(f); close(f);
} }
break; 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: case NTO:
fname = redir->nfile.expfname; 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) if ((f = open(fname, O_WRONLY|O_CREAT|O_TRUNC, 0666)) < 0)
error("cannot create %s: %s", fname, errmsg(errno, E_CREAT)); error("cannot create %s: %s", fname, strerror(errno));
#else goto movefd;
if ((f = creat(fname, 0666)) < 0) case NCLOBBER:
error("cannot create %s: %s", fname, errmsg(errno, E_CREAT)); fname = redir->nfile.expfname;
#endif if ((f = open(fname, O_WRONLY|O_CREAT|O_TRUNC, 0666)) < 0)
error("cannot create %s: %s", fname, strerror(errno));
goto movefd; goto movefd;
case NAPPEND: case NAPPEND:
fname = redir->nfile.expfname; fname = redir->nfile.expfname;
#ifdef O_APPEND
if ((f = open(fname, O_WRONLY|O_CREAT|O_APPEND, 0666)) < 0) if ((f = open(fname, O_WRONLY|O_CREAT|O_APPEND, 0666)) < 0)
error("cannot create %s: %s", fname, errmsg(errno, E_CREAT)); error("cannot create %s: %s", fname, strerror(errno));
#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
goto movefd; goto movefd;
case NTOFD: case NTOFD:
case NFROMFD: case NFROMFD:
@ -198,7 +216,9 @@ movefd:
if (memory[redir->ndup.dupfd]) if (memory[redir->ndup.dupfd])
memory[fd] = 1; memory[fd] = 1;
else else
copyfd(redir->ndup.dupfd, fd); dup2(redir->ndup.dupfd, fd);
} else {
close(fd);
} }
break; break;
case NHERE: case NHERE:
@ -219,14 +239,13 @@ movefd:
*/ */
STATIC int STATIC int
openhere(redir) openhere(union node *redir)
union node *redir;
{ {
int pip[2]; int pip[2];
int len; int len = 0;
if (pipe(pip) < 0) if (pipe(pip) < 0)
error("Pipe call failed"); error("Pipe call failed: %s", strerror(errno));
if (redir->type == NHERE) { if (redir->type == NHERE) {
len = strlen(redir->nhere.doc->narg.text); len = strlen(redir->nhere.doc->narg.text);
if (len <= PIPESIZE) { if (len <= PIPESIZE) {
@ -239,9 +258,7 @@ openhere(redir)
signal(SIGINT, SIG_IGN); signal(SIGINT, SIG_IGN);
signal(SIGQUIT, SIG_IGN); signal(SIGQUIT, SIG_IGN);
signal(SIGHUP, SIG_IGN); signal(SIGHUP, SIG_IGN);
#ifdef SIGTSTP
signal(SIGTSTP, SIG_IGN); signal(SIGTSTP, SIG_IGN);
#endif
signal(SIGPIPE, SIG_DFL); signal(SIGPIPE, SIG_DFL);
if (redir->type == NHERE) if (redir->type == NHERE)
xwrite(pip[1], redir->nhere.doc->narg.text, len); xwrite(pip[1], redir->nhere.doc->narg.text, len);
@ -261,18 +278,20 @@ out:
*/ */
void void
popredir() { popredir(void)
register struct redirtab *rp = redirlist; {
struct redirtab *rp = redirlist;
int i; int i;
for (i = 0 ; i < 10 ; i++) { for (i = 0 ; i < 10 ; i++) {
if (rp->renamed[i] != EMPTY) { if (rp->renamed[i] != EMPTY) {
if (i == 0) if (i == 0)
fd0_redirected--; fd0_redirected--;
close(i);
if (rp->renamed[i] >= 0) { if (rp->renamed[i] >= 0) {
copyfd(rp->renamed[i], i); dup2(rp->renamed[i], i);
close(rp->renamed[i]); close(rp->renamed[i]);
} else {
close(i);
} }
} }
} }
@ -282,8 +301,6 @@ popredir() {
INTON; INTON;
} }
/* /*
* Undo all redirections. Called on error or interrupt. * Undo all redirections. Called on error or interrupt.
*/ */
@ -303,14 +320,21 @@ SHELLPROC {
#endif #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. * Discard all saved file descriptors.
*/ */
void void
clearredir() { clearredir(void)
register struct redirtab *rp; {
struct redirtab *rp;
int i; int i;
for (rp = redirlist ; rp ; rp = rp->next) { 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 * $PchId: redir.c,v 1.5 2006/05/22 12:27:37 philip Exp $
* if the source file descriptor is closed, EMPTY if there are no unused
* file descriptors left.
*/ */
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;
}

View file

@ -1,6 +1,6 @@
/*- /*-
* Copyright (c) 1991 The Regents of the University of California. * Copyright (c) 1991, 1993
* All rights reserved. * The Regents of the University of California. All rights reserved.
* *
* This code is derived from software contributed to Berkeley by * This code is derived from software contributed to Berkeley by
* Kenneth Almquist. * Kenneth Almquist.
@ -13,10 +13,6 @@
* 2. Redistributions in binary form must reproduce the above copyright * 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the * notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution. * 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 * 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 * may be used to endorse or promote products derived from this software
* without specific prior written permission. * without specific prior written permission.
@ -33,24 +29,21 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE. * 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 */ /* flags passed to redirect */
#define REDIR_PUSH 01 /* save previous values of file descriptors */ #define REDIR_PUSH 01 /* save previous values of file descriptors */
#define REDIR_BACKQ 02 /* save the command output in memory */ #define REDIR_BACKQ 02 /* save the command output in memory */
#ifdef __STDC__
union node; union node;
void redirect(union node *, int); void redirect(union node *, int);
void popredir(void); void popredir(void);
void clearredir(void);
int copyfd(int, int);
int fd0_redirected_p(void); int fd0_redirected_p(void);
#else void clearredir(void);
void redirect();
void popredir();
void clearredir(); /*
int copyfd(); * $PchId: redir.h,v 1.3 2006/03/29 14:13:34 philip Exp $
int fd0_redirected_p(); */
#endif

463
commands/ash/setmode.c Normal file
View 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 $
*/

View file

@ -1,6 +1,6 @@
/*- /*-
* Copyright (c) 1991 The Regents of the University of California. * Copyright (c) 1991, 1993
* All rights reserved. * The Regents of the University of California. All rights reserved.
* *
* This code is derived from software contributed to Berkeley by * This code is derived from software contributed to Berkeley by
* Kenneth Almquist. * Kenneth Almquist.
@ -13,10 +13,6 @@
* 2. Redistributions in binary form must reproduce the above copyright * 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the * notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution. * 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 * 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 * may be used to endorse or promote products derived from this software
* without specific prior written permission. * without specific prior written permission.
@ -33,19 +29,17 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE. * 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: * The follow should be set to reflect the type of system you have:
* JOBS -> 1 if you have Berkeley job control, 0 otherwise. * 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. * TILDE -> 1 if you want the shell to expand ~logname.
* USEGETPW -> 1 if getpwnam() must be used to look up a name. * 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. * READLINE -> 1 if line editing by readline() should be enabled.
* define BSD if you are running 4.2 BSD or later. * define BSD if you are running 4.2 BSD or later.
* define SYSV if you are running under System V. * define SYSV if you are running under System V.
@ -56,52 +50,47 @@
* a quit signal will generate a core dump. * a quit signal will generate a core dump.
*/ */
#ifndef JOBS
#define JOBS 0 #define JOBS 1
/* 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.
*/
#if 0
#define SYMLINKS defined(S_ISLNK)
#else
#define SYMLINKS 0
#endif #endif
#ifndef BSD
#define DIRENT 1 #define BSD 1
#define UDIR 0 #endif
#define TILDE 1 #ifndef DEBUG
#define USEGETPW 0
#define ATTY 0
#define READLINE 1
#define HASHBANG 0
/* #define BSD */
#define POSIX 1
#define DEBUG 0 #define DEBUG 0
#endif
#define POSIX 1
/*
* 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)
#ifdef __STDC__
typedef void *pointer; typedef void *pointer;
#ifndef NULL #define STATIC static
#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 */ #define MKINIT /* empty */
#include <sys/cdefs.h>
#include <sys/types.h>
extern char nullstr[1]; /* null string */ extern char nullstr[1]; /* null string */
#if DEBUG #if DEBUG
#define TRACE(param) trace param #define TRACE(param) sh_trace param
#else #else
#define TRACE(param) #define TRACE(param)
#endif #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 $
*/

View file

@ -1,6 +1,6 @@
/*- /*-
* Copyright (c) 1991 The Regents of the University of California. * Copyright (c) 1991, 1993
* All rights reserved. * The Regents of the University of California. All rights reserved.
* *
* This code is derived from software contributed to Berkeley by * This code is derived from software contributed to Berkeley by
* Kenneth Almquist. * Kenneth Almquist.
@ -13,10 +13,6 @@
* 2. Redistributions in binary form must reproduce the above copyright * 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the * notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution. * 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 * 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 * may be used to endorse or promote products derived from this software
* without specific prior written permission. * without specific prior written permission.
@ -35,38 +31,54 @@
*/ */
#ifndef lint #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 */ #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 <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <errno.h> #include <errno.h>
#include "shell.h" #include "shell.h"
#include "parser.h" #include "parser.h"
#include "nodes.h" #include "nodes.h"
#include "mystring.h" #include "mystring.h"
#include "show.h"
#if DEBUG #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) static void
union node *n; showtree(union node *n)
{ {
trputs("showtree called\n"); trputs("showtree called\n");
shtree(n, 1, NULL, stdout); shtree(n, 1, NULL, stdout);
} }
static static void
shtree(n, ind, pfx, fp) shtree(union node *n, int ind, char *pfx, FILE *fp)
union node *n;
char *pfx;
FILE *fp;
{ {
struct nodelist *lp; struct nodelist *lp;
char *s; char *s;
if (n == NULL)
return;
indent(ind, pfx, fp); indent(ind, pfx, fp);
switch(n->type) { switch(n->type) {
case NSEMI: case NSEMI:
@ -109,10 +121,8 @@ binop:
static static void
shcmd(cmd, fp) shcmd(union node *cmd, FILE *fp)
union node *cmd;
FILE *fp;
{ {
union node *np; union node *np;
int first; int first;
@ -133,14 +143,20 @@ shcmd(cmd, fp)
case NTO: s = ">"; dftfd = 1; break; case NTO: s = ">"; dftfd = 1; break;
case NAPPEND: s = ">>"; dftfd = 1; break; case NAPPEND: s = ">>"; dftfd = 1; break;
case NTOFD: s = ">&"; dftfd = 1; break; case NTOFD: s = ">&"; dftfd = 1; break;
case NCLOBBER: s = ">|"; dftfd = 1; break;
case NFROM: s = "<"; dftfd = 0; break; case NFROM: s = "<"; dftfd = 0; break;
case NFROMTO: s = "<>"; dftfd = 0; break;
case NFROMFD: s = "<&"; dftfd = 0; break; case NFROMFD: s = "<&"; dftfd = 0; break;
default: s = "*error*"; dftfd = 0; break;
} }
if (np->nfile.fd != dftfd) if (np->nfile.fd != dftfd)
fprintf(fp, "%d", np->nfile.fd); fprintf(fp, "%d", np->nfile.fd);
fputs(s, fp); fputs(s, fp);
if (np->nfile.type == NTOFD || np->nfile.type == NFROMFD) { if (np->nfile.type == NTOFD || np->nfile.type == NFROMFD) {
if (np->ndup.dupfd >= 0)
fprintf(fp, "%d", np->ndup.dupfd); fprintf(fp, "%d", np->ndup.dupfd);
else
fprintf(fp, "-");
} else { } else {
sharg(np->nfile.fname, fp); sharg(np->nfile.fname, fp);
} }
@ -150,10 +166,8 @@ shcmd(cmd, fp)
static static void
sharg(arg, fp) sharg(union node *arg, FILE *fp)
union node *arg;
FILE *fp;
{ {
char *p; char *p;
struct nodelist *bqlist; struct nodelist *bqlist;
@ -174,10 +188,15 @@ sharg(arg, fp)
putc('$', fp); putc('$', fp);
putc('{', fp); putc('{', fp);
subtype = *++p; subtype = *++p;
if (subtype == VSLENGTH)
putc('#', fp);
while (*p != '=') while (*p != '=')
putc(*p++, fp); putc(*p++, fp);
if (subtype & VSNUL) if (subtype & VSNUL)
putc(':', fp); putc(':', fp);
switch (subtype & VSTYPE) { switch (subtype & VSTYPE) {
case VSNORMAL: case VSNORMAL:
putc('}', fp); putc('}', fp);
@ -194,6 +213,22 @@ sharg(arg, fp)
case VSASSIGN: case VSASSIGN:
putc('=', fp); putc('=', fp);
break; 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: default:
printf("<subtype %d>", subtype); printf("<subtype %d>", subtype);
} }
@ -216,10 +251,8 @@ sharg(arg, fp)
} }
static static void
indent(amount, pfx, fp) indent(int amount, char *pfx, FILE *fp)
char *pfx;
FILE *fp;
{ {
int i; int i;
@ -229,8 +262,6 @@ indent(amount, pfx, fp)
putc('\t', fp); putc('\t', fp);
} }
} }
#endif
/* /*
@ -247,52 +278,48 @@ int debug = 0;
#endif #endif
trputc(c) { static void
#if DEBUG trputc(int c)
{
if (tracefile == NULL) if (tracefile == NULL)
return; return;
putc(c, tracefile); putc(c, tracefile);
if (c == '\n') if (c == '\n')
fflush(tracefile); fflush(tracefile);
#endif
} }
trace(fmt, a1, a2, a3, a4, a5, a6, a7, a8) void
char *fmt; sh_trace(const char *fmt, ...)
{ {
#if DEBUG va_list va;
int e = errno; va_start(va, fmt);
if (tracefile == NULL) if (tracefile != NULL) {
return; (void) vfprintf(tracefile, fmt, va);
fprintf(tracefile, fmt, a1, a2, a3, a4, a5, a6, a7, a8);
if (strchr(fmt, '\n')) if (strchr(fmt, '\n'))
fflush(tracefile); (void) fflush(tracefile);
errno = e; }
#endif va_end(va);
} }
trputs(s) void
char *s; trputs(char *s)
{ {
#if DEBUG
if (tracefile == NULL) if (tracefile == NULL)
return; return;
fputs(s, tracefile); fputs(s, tracefile);
if (strchr(s, '\n')) if (strchr(s, '\n'))
fflush(tracefile); fflush(tracefile);
#endif
} }
trstring(s) static void
char *s; trstring(char *s)
{ {
register char *p; char *p;
char c; char c;
#if DEBUG
if (tracefile == NULL) if (tracefile == NULL)
return; return;
putc('"', tracefile); putc('"', tracefile);
@ -324,14 +351,12 @@ backslash: putc('\\', tracefile);
} }
} }
putc('"', tracefile); putc('"', tracefile);
#endif
} }
trargs(ap) void
char **ap; trargs(char **ap)
{ {
#if DEBUG
if (tracefile == NULL) if (tracefile == NULL)
return; return;
while (*ap) { while (*ap) {
@ -342,36 +367,43 @@ trargs(ap)
putc('\n', tracefile); putc('\n', tracefile);
} }
fflush(tracefile); fflush(tracefile);
#endif
} }
opentrace() { void
opentrace(void)
{
char s[100]; char s[100];
char *p;
char *getenv();
int flags; int flags;
#if DEBUG
if (!debug) if (!debug)
return; return;
#ifdef not_this_way
{
char *p;
if ((p = getenv("HOME")) == NULL) { if ((p = getenv("HOME")) == NULL) {
if (getuid() == 0) if (geteuid() == 0)
p = "/"; p = "/";
else else
p = "/tmp"; p = "/tmp";
} }
scopy(p, s); scopy(p, s);
strcat(s, "/trace"); strcat(s, "/trace");
}
#else
scopy("./trace", s);
#endif /* not_this_way */
if ((tracefile = fopen(s, "a")) == NULL) { 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; return;
} }
#ifdef O_APPEND
if ((flags = fcntl(fileno(tracefile), F_GETFL, 0)) >= 0) if ((flags = fcntl(fileno(tracefile), F_GETFL, 0)) >= 0)
fcntl(fileno(tracefile), F_SETFL, flags | O_APPEND); fcntl(fileno(tracefile), F_SETFL, flags | O_APPEND);
#endif
fputs("\nTracing started.\n", tracefile); fputs("\nTracing started.\n", tracefile);
fflush(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
View 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 $
*/

View file

@ -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

View file

@ -1,6 +1,6 @@
/*- /*-
* Copyright (c) 1991 The Regents of the University of California. * Copyright (c) 1991, 1993
* All rights reserved. * The Regents of the University of California. All rights reserved.
* *
* This code is derived from software contributed to Berkeley by * This code is derived from software contributed to Berkeley by
* Kenneth Almquist. * Kenneth Almquist.
@ -13,10 +13,6 @@
* 2. Redistributions in binary form must reproduce the above copyright * 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the * notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution. * 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 * 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 * may be used to endorse or promote products derived from this software
* without specific prior written permission. * without specific prior written permission.
@ -35,25 +31,45 @@
*/ */
#ifndef lint #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 */ #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 "shell.h"
#include "main.h" #include "main.h"
#include "nodes.h" /* for other headers */ #include "nodes.h" /* for other headers */
#include "eval.h" #include "eval.h"
#include "jobs.h" #include "jobs.h"
#include "show.h"
#include "options.h" #include "options.h"
#include "syntax.h" #include "syntax.h"
#include "signames.h"
#include "output.h" #include "output.h"
#include "memalloc.h" #include "memalloc.h"
#include "error.h" #include "error.h"
#include "trap.h" #include "trap.h"
#include "mystring.h" #include "mystring.h"
#include <sys/types.h> #if !defined(NO_HISTORY) && !defined(EDITLINE)
#include <signal.h> #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 * 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_DFL 1 /* default signal handling (SIG_DFL) */
#define S_CATCH 2 /* signal is caught */ #define S_CATCH 2 /* signal is caught */
#define S_IGN 3 /* signal is ignored (SIG_IGN) */ #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 */
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 */ 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(' ');
}
}
}
/* /*
* The trap builtin. * The trap builtin.
*/ */
int
trapcmd(argc, argv) char **argv; { trapcmd(int argc, char **argv)
{
char *action; char *action;
char **ap;
int signo; int signo;
if (argc <= 1) { if (argc <= 1) {
for (signo = 0 ; signo <= MAXSIG ; signo++) { for (signo = 0 ; signo < _NSIG ; signo++) {
if (trap[signo] != NULL) if (trap[signo] != NULL) {
out1fmt("%d: %s\n", signo, trap[signo]); 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; return 0;
} }
ap = argv + 1;
if (is_number(*ap))
action = NULL; action = NULL;
else if (*++argv && strcmp(*argv, "--") == 0)
action = *ap++; argv++;
while (*ap) { if (*argv && sigstring_to_signum(*argv) == -1) {
if ((signo = number(*ap)) < 0 || signo > MAXSIG) if ((*argv)[0] != '-') {
error("%s: bad trap", *ap); 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; INTOFF;
if (action) if (action)
action = savestr(action); action = savestr(action);
@ -107,22 +213,21 @@ trapcmd(argc, argv) char **argv; {
if (signo != 0) if (signo != 0)
setsignal(signo); setsignal(signo);
INTON; INTON;
ap++; argv++;
} }
return 0; return 0;
} }
/* /*
* Clear traps on a fork. * Clear traps on a fork.
*/ */
void void
clear_traps() { clear_traps(void)
char **tp; {
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 */ if (*tp && **tp) { /* trap not NULL or SIG_IGN */
INTOFF; INTOFF;
ckfree(*tp); ckfree(*tp);
@ -135,18 +240,16 @@ clear_traps() {
} }
/* /*
* Set the signal handler for the specified signal. The routine figures * Set the signal handler for the specified signal. The routine figures
* out what it should be set to. * out what it should be set to.
*/ */
void
int setsignal(int signo)
setsignal(signo) { {
int action; int action;
sig_t sigact; sig_T sig, sigact = SIG_DFL;
char *t; char *t;
extern void onsig();
if ((t = trap[signo]) == NULL) if ((t = trap[signo]) == NULL)
action = S_DFL; action = S_DFL;
@ -154,10 +257,9 @@ setsignal(signo) {
action = S_CATCH; action = S_CATCH;
else else
action = S_IGN; action = S_IGN;
if (rootshell && action == S_DFL) { if (action == S_DFL) {
switch (signo) { switch (signo) {
case SIGINT: case SIGINT:
if (iflag)
action = S_CATCH; action = S_CATCH;
break; break;
case SIGQUIT: case SIGQUIT:
@ -169,68 +271,103 @@ setsignal(signo) {
break; break;
} }
#endif #endif
/* FALLTHROUGH */ action = S_CATCH;
break;
case SIGTERM: case SIGTERM:
if (iflag) if (rootshell && iflag)
action = S_IGN; action = S_IGN;
break; break;
#if JOBS #if JOBS
case SIGTSTP: case SIGTSTP:
case SIGTTOU: case SIGTTOU:
if (jflag) if (rootshell && mflag)
action = S_IGN; action = S_IGN;
break; break;
#endif
#ifndef NO_HISTORY
case SIGWINCH:
if (rootshell && iflag)
action = S_CATCH;
break;
#endif #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. * current setting unknown
* A signal can be ignored that shouldn't be.
*/ */
if ((int)(sigact = signal(signo, SIG_IGN)) == -1) if (!getsigaction(signo, &sigact)) {
error("Signal system call failed"); /*
* 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) { if (sigact == SIG_IGN) {
if (mflag && (signo == SIGTSTP ||
signo == SIGTTIN || signo == SIGTTOU)) {
*t = S_IGN; /* don't hard ignore these */
} else
*t = S_HARD_IGN; *t = S_HARD_IGN;
} else { } else {
*t = S_IGN; *t = S_RESET; /* force to be set */
} }
} }
if (*t == S_HARD_IGN || *t == action) if (*t == S_HARD_IGN || *t == action)
return 0; return;
switch (action) { switch (action) {
case S_DFL: sigact = SIG_DFL; break; case S_DFL: sigact = SIG_DFL; break;
case S_CATCH: sigact = onsig; break; case S_CATCH: sigact = onsig; break;
case S_IGN: sigact = SIG_IGN; break; case S_IGN: sigact = SIG_IGN; break;
} }
*t = action; *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. * Ignore a signal.
*/ */
void void
ignoresig(signo) { ignoresig(int signo)
if (sigmode[signo - 1] != S_IGN && sigmode[signo - 1] != S_HARD_IGN) { {
if (sigmode[signo] != S_IGN && sigmode[signo] != S_HARD_IGN) {
signal(signo, SIG_IGN); signal(signo, SIG_IGN);
} }
sigmode[signo - 1] = S_HARD_IGN; sigmode[signo] = S_HARD_IGN;
} }
#ifdef mkinit #ifdef mkinit
INCLUDE "signames.h" INCLUDE <signal.h>
INCLUDE "trap.h" INCLUDE "trap.h"
SHELLPROC { SHELLPROC {
char *sm; char *sm;
clear_traps(); clear_traps();
for (sm = sigmode ; sm < sigmode + MAXSIG ; sm++) { for (sm = sigmode ; sm < sigmode + _NSIG ; sm++) {
if (*sm == S_IGN) if (*sm == S_IGN)
*sm = S_HARD_IGN; *sm = S_HARD_IGN;
} }
@ -238,82 +375,119 @@ SHELLPROC {
#endif #endif
/* /*
* Signal handler. * Signal handler.
*/ */
static void
onsig(int signo)
{
void #ifndef BSD
onsig(signo) {
signal(signo, onsig); signal(signo, onsig);
#endif
if (signo == SIGINT && trap[SIGINT] == NULL) { if (signo == SIGINT && trap[SIGINT] == NULL) {
onint(); onint();
return; 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 * Called to execute a trap. Perhaps we should avoid entering new trap
* handlers while we are executing a trap handler. * handlers while we are executing a trap handler.
*/ */
void void
dotrap() { dotrap(void)
{
int i; int i;
int savestatus; int savestatus;
in_dotrap++;
for (;;) { for (;;) {
for (i = 1 ; ; i++) { for (i = 1; i < _NSIG; i++) {
if (gotsig[i - 1]) if (gotsig[i]) {
break; gotsig[i] = 0;
if (i >= MAXSIG) if (trap[i]) {
goto done; /*
} * Ignore SIGCHLD to avoid infinite
gotsig[i - 1] = 0; * recursion if the trap action does
* a fork.
*/
if (i == SIGCHLD)
ignore_sigchld++;
savestatus = exitstatus; savestatus = exitstatus;
evalstring(trap[i]); evalstring(trap[i]);
exitstatus = savestatus; exitstatus = savestatus;
if (i == SIGCHLD)
ignore_sigchld--;
} }
done: break;
}
}
if (i >= _NSIG)
break;
}
in_dotrap--;
pendingsigs = 0; pendingsigs = 0;
} }
/* /*
* Controls whether the shell is interactive or not. * Controls whether the shell is interactive or not.
*/ */
int is_interactive;
void void
setinteractive(on) { setinteractive(int on)
{
if (on == is_interactive) if (on == is_interactive)
return; return;
setsignal(SIGINT); setsignal(SIGINT);
setsignal(SIGQUIT); setsignal(SIGQUIT);
setsignal(SIGTERM); setsignal(SIGTERM);
#ifndef NO_HISTORY
setsignal(SIGWINCH);
#endif
is_interactive = on; is_interactive = on;
} }
/* /*
* Called to exit the shell. * Called to exit the shell.
*/ */
void void
exitshell(status) { exitshell(int status)
{
struct jmploc loc1, loc2; struct jmploc loc1, loc2;
char *p; char *p;
TRACE(("exitshell(%d) pid=%d\n", status, getpid())); TRACE(("exitshell(%d) pid=%d\n", status, getpid()));
if (setjmp(loc1.loc)) goto l1; if (setjmp(loc1.loc)) {
if (setjmp(loc2.loc)) goto l2; goto l1;
}
if (setjmp(loc2.loc)) {
goto l2;
}
handler = &loc1; handler = &loc1;
if ((p = trap[0]) != NULL && *p != '\0') { if ((p = trap[0]) != NULL && *p != '\0') {
trap[0] = NULL; trap[0] = NULL;
@ -326,3 +500,85 @@ l1: handler = &loc2; /* probably unnecessary */
#endif #endif
l2: _exit(status); 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 $
*/

View file

@ -1,6 +1,6 @@
/*- /*-
* Copyright (c) 1991 The Regents of the University of California. * Copyright (c) 1991, 1993
* All rights reserved. * The Regents of the University of California. All rights reserved.
* *
* This code is derived from software contributed to Berkeley by * This code is derived from software contributed to Berkeley by
* Kenneth Almquist. * Kenneth Almquist.
@ -13,10 +13,6 @@
* 2. Redistributions in binary form must reproduce the above copyright * 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the * notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution. * 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 * 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 * may be used to endorse or promote products derived from this software
* without specific prior written permission. * without specific prior written permission.
@ -33,23 +29,24 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE. * 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 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); void clear_traps(void);
int setsignal(int); void setsignal(int);
void ignoresig(int); void ignoresig(int);
void dotrap(void); void dotrap(void);
void setinteractive(int); void setinteractive(int);
void exitshell(int); void exitshell(int);
#else char *strsiglist(int);
void clear_traps();
int setsignal(); /*
void ignoresig(); * $PchId: trap.h,v 1.6 2006/05/22 12:48:30 philip Exp $
void dotrap(); */
void setinteractive();
void exitshell();
#endif

View file

@ -1,6 +1,6 @@
/*- /*-
* Copyright (c) 1991 The Regents of the University of California. * Copyright (c) 1991, 1993
* All rights reserved. * The Regents of the University of California. All rights reserved.
* *
* This code is derived from software contributed to Berkeley by * This code is derived from software contributed to Berkeley by
* Kenneth Almquist. * Kenneth Almquist.
@ -13,10 +13,6 @@
* 2. Redistributions in binary form must reproduce the above copyright * 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the * notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution. * 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 * 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 * may be used to endorse or promote products derived from this software
* without specific prior written permission. * without specific prior written permission.
@ -35,13 +31,27 @@
*/ */
#ifndef lint #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 */ #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. * Shell variables.
*/ */
#include <locale.h>
#include "shell.h" #include "shell.h"
#include "output.h" #include "output.h"
#include "expand.h" #include "expand.h"
@ -55,7 +65,16 @@ static char sccsid[] = "@(#)var.c 5.3 (Berkeley) 4/12/91";
#include "memalloc.h" #include "memalloc.h"
#include "error.h" #include "error.h"
#include "mystring.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 #define VTABSIZE 39
@ -64,48 +83,57 @@ struct varinit {
struct var *var; struct var *var;
int flags; int flags;
char *text; char *text;
void (*func)(const char *);
}; };
#if ATTY #ifndef NO_HISTORY
struct var vatty; struct var vhistsize;
#endif #endif
struct var vifs; struct var vifs;
struct var vmail; struct var vmail;
struct var vmpath; struct var vmpath;
struct var vpath; struct var vpath;
struct var vppid;
struct var vps1; struct var vps1;
struct var vps2; struct var vps2;
struct var vpse; struct var vpse;
struct var vvers; struct var vvers;
#if ATTY STATIC struct var voptind;
struct var vterm;
#endif
const struct varinit varinit[] = { STATIC const struct varinit varinit[] = {
#if ATTY #if !defined(NO_HISTORY) && !defined(EDITLINE)
{&vatty, VSTRFIXED|VTEXTFIXED|VUNSET, "ATTY="}, { &vhistsize, VSTRFIXED|VTEXTFIXED|VUNSET, "HISTSIZE=",
sethistsize },
#endif #endif
{&vifs, VSTRFIXED|VTEXTFIXED, "IFS= \t\n"}, { &vifs, VSTRFIXED|VTEXTFIXED, "IFS= \t\n",
{&vmail, VSTRFIXED|VTEXTFIXED|VUNSET, "MAIL="}, NULL },
{&vmpath, VSTRFIXED|VTEXTFIXED|VUNSET, "MAILPATH="}, { &vmail, VSTRFIXED|VTEXTFIXED|VUNSET, "MAIL=",
{&vpath, VSTRFIXED|VTEXTFIXED, "PATH=:/bin:/usr/bin"}, NULL },
{ &vmpath, VSTRFIXED|VTEXTFIXED|VUNSET, "MAILPATH=",
NULL },
{ &vpath, VSTRFIXED|VTEXTFIXED, "PATH=" _PATH_DEFPATH,
changepath },
{ &vppid, VSTRFIXED|VTEXTFIXED|VUNSET, "PPID=",
NULL },
/* /*
* vps1 depends on uid * vps1 depends on uid
*/ */
{&vps2, VSTRFIXED|VTEXTFIXED, "PS2=> "}, { &vps2, VSTRFIXED|VTEXTFIXED, "PS2=> ",
{&vpse, VSTRFIXED|VTEXTFIXED, "PSE=* "}, NULL },
#if ATTY { &vpse, VSTRFIXED|VTEXTFIXED|VUNSET, "PSE=",
{&vterm, VSTRFIXED|VTEXTFIXED|VUNSET, "TERM="}, NULL },
#endif { &voptind, VSTRFIXED|VTEXTFIXED, "OPTIND=1",
{NULL, 0, NULL} getoptsreset },
{ NULL, 0, NULL,
NULL }
}; };
struct var *vartab[VTABSIZE]; STATIC struct var *vartab[VTABSIZE];
STATIC void unsetvar __P((char *)); STATIC struct var **hashvar(char *);
STATIC struct var **hashvar __P((char *)); STATIC int varequal(char *, char *);
STATIC int varequal __P((char *, char *)); STATIC int localevar(char *);
/* /*
* Initialize the varable symbol tables and import the environment * Initialize the varable symbol tables and import the environment
@ -133,7 +161,9 @@ INIT {
*/ */
void void
initvar() { initvar(void)
{
char ppid[20];
const struct varinit *ip; const struct varinit *ip;
struct var *vp; struct var *vp;
struct var **vpp; struct var **vpp;
@ -145,6 +175,7 @@ initvar() {
*vpp = vp; *vpp = vp;
vp->text = ip->text; vp->text = ip->text;
vp->flags = ip->flags; vp->flags = ip->flags;
vp->func = ip->func;
} }
} }
/* /*
@ -154,19 +185,47 @@ initvar() {
vpp = hashvar("PS1="); vpp = hashvar("PS1=");
vps1.next = *vpp; vps1.next = *vpp;
*vpp = &vps1; *vpp = &vps1;
vps1.text = getuid() ? "PS1=$ " : "PS1=# "; vps1.text = geteuid() ? "PS1=$ " : "PS1=# ";
vps1.flags = VSTRFIXED|VTEXTFIXED; 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. * flags of the variable. If val is NULL, the variable is unset.
*/ */
void void
setvar(name, val, flags) setvar(char *name, char *val, int flags)
char *name, *val;
{ {
char *p, *q; char *p, *q;
int len; int len;
@ -176,8 +235,9 @@ setvar(name, val, flags)
isbad = 0; isbad = 0;
p = name; p = name;
if (! is_name(*p++)) if (! is_name(*p))
isbad = 1; isbad = 1;
p++;
for (;;) { for (;;) {
if (! is_in_name(*p)) { if (! is_in_name(*p)) {
if (*p == '\0' || *p == '=') if (*p == '\0' || *p == '=')
@ -188,7 +248,7 @@ setvar(name, val, flags)
} }
namelen = p - name; namelen = p - name;
if (isbad) 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' */ len = namelen + 2; /* 2 is space for '=' and '\0' */
if (val == NULL) { if (val == NULL) {
flags |= VUNSET; flags |= VUNSET;
@ -206,7 +266,26 @@ setvar(name, val, flags)
setvareq(nameeq, 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 * Same as setvar except that the variable and value are passed in
@ -216,28 +295,42 @@ setvar(name, val, flags)
*/ */
void void
setvareq(s, flags) setvareq(char *s, int flags)
char *s;
{ {
struct var *vp, **vpp; struct var *vp, **vpp;
int len;
if (aflag)
flags |= VEXPORT;
vpp = hashvar(s); vpp = hashvar(s);
for (vp = *vpp ; vp ; vp = vp->next) { for (vp = *vpp ; vp ; vp = vp->next) {
if (varequal(s, vp->text)) { if (varequal(s, vp->text)) {
if (vp->flags & VREADONLY) { if (vp->flags & VREADONLY) {
int len = strchr(s, '=') - s; len = strchr(s, '=') - s;
error("%.*s: is read only", len, s); error("%.*s: is read only", len, s);
} }
INTOFF; 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) if ((vp->flags & (VTEXTFIXED|VSTACK)) == 0)
ckfree(vp->text); ckfree(vp->text);
vp->flags &= ~(VTEXTFIXED|VSTACK|VUNSET); vp->flags &= ~(VTEXTFIXED|VSTACK|VUNSET);
vp->flags |= flags; vp->flags |= flags;
vp->text = s; 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())) if (vp == &vmpath || (vp == &vmail && ! mpathset()))
chkmail(1); chkmail(1);
if ((vp->flags & VEXPORT) && localevar(s)) {
putenv(s);
(void) setlocale(LC_ALL, "");
}
INTON; INTON;
return; return;
} }
@ -247,7 +340,14 @@ setvareq(s, flags)
vp->flags = flags; vp->flags = flags;
vp->text = s; vp->text = s;
vp->next = *vpp; vp->next = *vpp;
vp->func = NULL;
INTOFF;
*vpp = vp; *vpp = vp;
if ((vp->flags & VEXPORT) && localevar(s)) {
putenv(s);
(void) setlocale(LC_ALL, "");
}
INTON;
} }
@ -257,8 +357,7 @@ setvareq(s, flags)
*/ */
void void
listsetvar(list) listsetvar(struct strlist *list)
struct strlist *list;
{ {
struct strlist *lp; struct strlist *lp;
@ -276,8 +375,7 @@ listsetvar(list)
*/ */
char * char *
lookupvar(name) lookupvar(char *name)
char *name;
{ {
struct var *v; struct var *v;
@ -300,8 +398,7 @@ lookupvar(name)
*/ */
char * char *
bltinlookup(name, doall) bltinlookup(char *name, int doall)
char *name;
{ {
struct strlist *sp; struct strlist *sp;
struct var *v; struct var *v;
@ -312,8 +409,8 @@ bltinlookup(name, doall)
} }
for (v = *hashvar(name) ; v ; v = v->next) { for (v = *hashvar(name) ; v ; v = v->next) {
if (varequal(v->text, name)) { if (varequal(v->text, name)) {
if (v->flags & VUNSET if ((v->flags & VUNSET)
|| ! doall && (v->flags & VEXPORT) == 0) || (!doall && (v->flags & VEXPORT) == 0))
return NULL; return NULL;
return strchr(v->text, '=') + 1; return strchr(v->text, '=') + 1;
} }
@ -329,7 +426,8 @@ bltinlookup(name, doall)
*/ */
char ** char **
environment() { environment(void)
{
int nenv; int nenv;
struct var **vpp; struct var **vpp;
struct var *vp; struct var *vp;
@ -359,15 +457,14 @@ environment() {
*/ */
#ifdef mkinit #ifdef mkinit
MKINIT void shprocvar();
SHELLPROC { SHELLPROC {
shprocvar(); shprocvar();
} }
#endif #endif
void void
shprocvar() { shprocvar(void)
{
struct var **vpp; struct var **vpp;
struct var *vp, **prev; struct var *vp, **prev;
@ -400,14 +497,21 @@ shprocvar() {
*/ */
int int
showvarscmd(argc, argv) char **argv; { showvarscmd(int argc __unused, char **argv __unused)
{
struct var **vpp; struct var **vpp;
struct var *vp; struct var *vp;
const char *s;
for (vpp = vartab ; vpp < vartab + VTABSIZE ; vpp++) { for (vpp = vartab ; vpp < vartab + VTABSIZE ; vpp++) {
for (vp = *vpp ; vp ; vp = vp->next) { for (vp = *vpp ; vp ; vp = vp->next) {
if ((vp->flags & VUNSET) == 0) if (vp->flags & VUNSET)
out1fmt("%s\n", vp->text); continue;
for (s = vp->text; *s != '='; s++)
out1c(*s);
out1c('=');
out1qstr(s + 1);
out1c('\n');
} }
} }
return 0; return 0;
@ -420,15 +524,35 @@ showvarscmd(argc, argv) char **argv; {
*/ */
int int
exportcmd(argc, argv) char **argv; { exportcmd(int argc, char **argv)
{
struct var **vpp; struct var **vpp;
struct var *vp; struct var *vp;
char *name; char *name;
char *p; char *p;
char *cmdname;
int ch, values;
int flag = argv[0][0] == 'r'? VREADONLY : VEXPORT; 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); listsetvar(cmdenviron);
if (argc > 1) { if (argc != 0) {
while ((name = *argptr++) != NULL) { while ((name = *argptr++) != NULL) {
if ((p = strchr(name, '=')) != NULL) { if ((p = strchr(name, '=')) != NULL) {
p++; p++;
@ -436,7 +560,12 @@ exportcmd(argc, argv) char **argv; {
vpp = hashvar(name); vpp = hashvar(name);
for (vp = *vpp ; vp ; vp = vp->next) { for (vp = *vpp ; vp ; vp = vp->next) {
if (varequal(vp->text, name)) { if (varequal(vp->text, name)) {
vp->flags |= flag; vp->flags |= flag;
if ((vp->flags & VEXPORT) && localevar(vp->text)) {
putenv(vp->text);
(void) setlocale(LC_ALL, "");
}
goto found; goto found;
} }
} }
@ -448,8 +577,16 @@ found:;
for (vpp = vartab ; vpp < vartab + VTABSIZE ; vpp++) { for (vpp = vartab ; vpp < vartab + VTABSIZE ; vpp++) {
for (vp = *vpp ; vp ; vp = vp->next) { for (vp = *vpp ; vp ; vp = vp->next) {
if (vp->flags & flag) { if (vp->flags & flag) {
if (values) {
out1str(cmdname);
out1c(' ');
}
for (p = vp->text ; *p != '=' ; p++) for (p = vp->text ; *p != '=' ; p++)
out1c(*p); out1c(*p);
if (values && !(vp->flags & VUNSET)) {
out1c('=');
out1qstr(p + 1);
}
out1c('\n'); out1c('\n');
} }
} }
@ -463,7 +600,9 @@ found:;
* The "local" command. * The "local" command.
*/ */
localcmd(argc, argv) char **argv; { int
localcmd(int argc __unused, char **argv __unused)
{
char *name; char *name;
if (! in_function()) if (! in_function())
@ -483,8 +622,7 @@ localcmd(argc, argv) char **argv; {
*/ */
void void
mklocal(name) mklocal(char *name)
char *name;
{ {
struct localvar *lvp; struct localvar *lvp;
struct var **vpp; struct var **vpp;
@ -493,8 +631,8 @@ mklocal(name)
INTOFF; INTOFF;
lvp = ckmalloc(sizeof (struct localvar)); lvp = ckmalloc(sizeof (struct localvar));
if (name[0] == '-' && name[1] == '\0') { if (name[0] == '-' && name[1] == '\0') {
lvp->text = ckmalloc(sizeof optval); lvp->text = ckmalloc(sizeof optlist);
bcopy(optval, lvp->text, sizeof optval); memcpy(lvp->text, optlist, sizeof optlist);
vp = NULL; vp = NULL;
} else { } else {
vpp = hashvar(name); vpp = hashvar(name);
@ -527,7 +665,8 @@ mklocal(name)
*/ */
void void
poplocalvars() { poplocalvars(void)
{
struct localvar *lvp; struct localvar *lvp;
struct var *vp; struct var *vp;
@ -535,10 +674,10 @@ poplocalvars() {
localvars = lvp->next; localvars = lvp->next;
vp = lvp->vp; vp = lvp->vp;
if (vp == NULL) { /* $- saved */ if (vp == NULL) { /* $- saved */
bcopy(lvp->text, optval, sizeof optval); memcpy(optlist, lvp->text, sizeof optlist);
ckfree(lvp->text); ckfree(lvp->text);
} else if ((lvp->flags & (VUNSET|VSTRFIXED)) == VUNSET) { } else if ((lvp->flags & (VUNSET|VSTRFIXED)) == VUNSET) {
unsetvar(vp->text); (void)unsetvar(vp->text);
} else { } else {
if ((vp->flags & VTEXTFIXED) == 0) if ((vp->flags & VTEXTFIXED) == 0)
ckfree(vp->text); ckfree(vp->text);
@ -550,7 +689,9 @@ poplocalvars() {
} }
setvarcmd(argc, argv) char **argv; { int
setvarcmd(int argc, char **argv)
{
if (argc <= 2) if (argc <= 2)
return unsetcmd(argc, argv); return unsetcmd(argc, argv);
else if (argc == 3) else if (argc == 3)
@ -567,14 +708,31 @@ setvarcmd(argc, argv) char **argv; {
* with the same name. * with the same name.
*/ */
unsetcmd(argc, argv) char **argv; { int
unsetcmd(int argc __unused, char **argv __unused)
{
char **ap; char **ap;
int i;
int flg_func = 0;
int flg_var = 0;
int ret = 0;
for (ap = argv + 1 ; *ap ; ap++) { while ((i = nextopt("vf")) != '\0') {
unsetfunc(*ap); if (i == 'f')
unsetvar(*ap); 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,9 +740,8 @@ unsetcmd(argc, argv) char **argv; {
* Unset the specified variable. * Unset the specified variable.
*/ */
STATIC void int
unsetvar(s) unsetvar(char *s)
char *s;
{ {
struct var **vpp; struct var **vpp;
struct var *vp; struct var *vp;
@ -592,10 +749,14 @@ unsetvar(s)
vpp = hashvar(s); vpp = hashvar(s);
for (vp = *vpp ; vp ; vpp = &vp->next, vp = *vpp) { for (vp = *vpp ; vp ; vpp = &vp->next, vp = *vpp) {
if (varequal(vp->text, s)) { if (varequal(vp->text, s)) {
if (vp->flags & VREADONLY)
return (1);
INTOFF; INTOFF;
if (*(strchr(vp->text, '=') + 1) != '\0' if (*(strchr(vp->text, '=') + 1) != '\0')
|| vp->flags & VREADONLY) {
setvar(s, nullstr, 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; vp->flags |= VUNSET;
@ -606,9 +767,11 @@ unsetvar(s)
ckfree(vp); ckfree(vp);
} }
INTON; INTON;
return; return (0);
} }
} }
return (0);
} }
@ -618,14 +781,13 @@ unsetvar(s)
*/ */
STATIC struct var ** STATIC struct var **
hashvar(p) hashvar(char *p)
register char *p;
{ {
unsigned int hashval; unsigned int hashval;
hashval = *p << 4; hashval = ((unsigned char) *p) << 4;
while (*p && *p != '=') while (*p && *p != '=')
hashval += *p++; hashval += (unsigned char) *p++;
return &vartab[hashval % VTABSIZE]; return &vartab[hashval % VTABSIZE];
} }
@ -638,8 +800,7 @@ hashvar(p)
*/ */
STATIC int STATIC int
varequal(p, q) varequal(char *p, char *q)
register char *p, *q;
{ {
while (*p == *q++) { while (*p == *q++) {
if (*p++ == '=') if (*p++ == '=')
@ -649,3 +810,7 @@ varequal(p, q)
return 1; return 1;
return 0; return 0;
} }
/*
* $PchId: var.c,v 1.5 2006/05/22 12:28:49 philip Exp $
*/

View file

@ -1,6 +1,6 @@
/*- /*-
* Copyright (c) 1991 The Regents of the University of California. * Copyright (c) 1991, 1993
* All rights reserved. * The Regents of the University of California. All rights reserved.
* *
* This code is derived from software contributed to Berkeley by * This code is derived from software contributed to Berkeley by
* Kenneth Almquist. * Kenneth Almquist.
@ -13,10 +13,6 @@
* 2. Redistributions in binary form must reproduce the above copyright * 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the * notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution. * 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 * 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 * may be used to endorse or promote products derived from this software
* without specific prior written permission. * without specific prior written permission.
@ -33,7 +29,8 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE. * 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,18 +38,22 @@
*/ */
/* flags */ /* flags */
#define VEXPORT 01 /* variable is exported */ #define VEXPORT 0x01 /* variable is exported */
#define VREADONLY 02 /* variable cannot be modified */ #define VREADONLY 0x02 /* variable cannot be modified */
#define VSTRFIXED 04 /* variable struct is staticly allocated */ #define VSTRFIXED 0x04 /* variable struct is staticly allocated */
#define VTEXTFIXED 010 /* text is staticly allocated */ #define VTEXTFIXED 0x08 /* text is staticly allocated */
#define VSTACK 020 /* text is allocated on the stack */ #define VSTACK 0x10 /* text is allocated on the stack */
#define VUNSET 040 /* the variable is not set */ #define VUNSET 0x20 /* the variable is not set */
#define VNOFUNC 0x40 /* don't call the callback function */
struct var { struct var {
struct var *next; /* next entry in hash list */ struct var *next; /* next entry in hash list */
int flags; /* flags are defined above */ int flags; /* flags are defined above */
char *text; /* name=value */ char *text; /* name=value */
void (*func)(const char *);
/* function to be called when */
/* the variable gets set/unset */
}; };
@ -66,18 +67,16 @@ struct localvar {
struct localvar *localvars; struct localvar *localvars;
#if ATTY
extern struct var vatty;
#endif
extern struct var vifs; extern struct var vifs;
extern struct var vmail; extern struct var vmail;
extern struct var vmpath; extern struct var vmpath;
extern struct var vpath; extern struct var vpath;
extern struct var vppid;
extern struct var vps1; extern struct var vps1;
extern struct var vps2; extern struct var vps2;
extern struct var vpse; extern struct var vpse;
#if ATTY #ifndef NO_HISTORY
extern struct var vterm; extern struct var vhistsize;
#endif #endif
/* /*
@ -87,43 +86,39 @@ extern struct var vterm;
*/ */
#define ifsval() (vifs.text + 4) #define ifsval() (vifs.text + 4)
#define ifsset() ((vifs.flags & VUNSET) == 0)
#define mailval() (vmail.text + 5) #define mailval() (vmail.text + 5)
#define mpathval() (vmpath.text + 9) #define mpathval() (vmpath.text + 9)
#define pathval() (vpath.text + 5) #define pathval() (vpath.text + 5)
#define ps1val() (vps1.text + 4) #define ps1val() (vps1.text + 4)
#define ps2val() (vps2.text + 4) #define ps2val() (vps2.text + 4)
#define pseval() (vpse.text + 4) #define pseval() (vpse.text + 4)
#if ATTY #define optindval() (voptind.text + 7)
#define termval() (vterm.text + 5) #ifndef NO_HISTORY
#define histsizeval() (vhistsize.text + 9)
#endif #endif
#if ATTY
#define attyset() ((vatty.flags & VUNSET) == 0)
#endif
#define mpathset() ((vmpath.flags & VUNSET) == 0) #define mpathset() ((vmpath.flags & VUNSET) == 0)
void initvar(void);
#ifdef __STDC__
void initvar();
void setvar(char *, char *, int); void setvar(char *, char *, int);
void setvareq(char *, int); void setvareq(char *, int);
struct strlist; struct strlist;
void listsetvar(struct strlist *); void listsetvar(struct strlist *);
char *lookupvar(char *); char *lookupvar(char *);
char *bltinlookup(char *, int); char *bltinlookup(char *, int);
char **environment(); char **environment(void);
void shprocvar(void);
int showvarscmd(int, char **); int showvarscmd(int, char **);
int exportcmd(int, char **);
int localcmd(int, char **);
void mklocal(char *); void mklocal(char *);
void poplocalvars(void); void poplocalvars(void);
#else int setvarcmd(int, char **);
void initvar(); int unsetcmd(int, char **);
void setvar(); int unsetvar(char *);
void setvareq(); int setvarsafe(char *, char *, int);
void listsetvar();
char *lookupvar(); /*
char *bltinlookup(); * $PchId: var.h,v 1.4 2006/03/29 12:04:45 philip Exp $
char **environment(); */
int showvarscmd();
void mklocal();
void poplocalvars();
#endif