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.
SRCS= builtins.c cd.c dirent.c error.c eval.c exec.c expand.c input.c \
SRCS= alias.c builtins.c cd.c error.c eval.c exec.c expand.c histedit.c \
input.c \
jobs.c mail.c main.c memalloc.c miscbltin.c mystring.c nodes.c \
options.c parser.c redir.c show.c signames.c syntax.c trap.c \
options.c parser.c redir.c setmode.c show.c signames.c syntax.c \
trap.c \
output.c var.c
OBJS= builtins.o cd.o dirent.o error.o eval.o exec.o expand.o input.o \
OBJS= alias.o builtins.o cd.o error.o eval.o exec.o expand.o histedit.o \
input.o \
jobs.o mail.o main.o memalloc.o miscbltin.o mystring.o nodes.o \
options.o parser.o redir.o show.o signames.o syntax.o trap.o \
options.o parser.o redir.o setmode.o show.o signames.o syntax.o \
trap.o \
output.o var.o init.o \
bltin/echo.o bltin/expr.o bltin/operators.o bltin/regexp.o
bltin/echo.o bltin/expr.o bltin/operators.o bltin/regexp.o \
arith.o arith_lex.o
#
# Set READLINE in shell.h and add -ledit to LIBS if you want to use the
# editline package by Simmule Turner and Rich Salz. (The big, bloated
# and GPL contaminated FSF readline should work too.)
#
CPPFLAGS= -DSHELL -I. -D_MINIX -D_POSIX_SOURCE
CFLAGS= -wo -i $(CPPFLAGS)
LIBS= -ledit
CC = exec cc
LEX=flex
YACC=yacc
.c.o:
$(CC) $(CFLAGS) -c $< -o $@
# Enable this line to disable command line editing
#EDIT=-DNO_HISTORY
# Enable this line to use the editline library instead of libedit
EDIT=-DEDITLINE
EDITLIB=-ledit
FLEXLIB=-lfl
# Enable this line if your system does not have a <paths.h>
NO_PATHS_H=-DNO_PATHS_H
# Enable this if you don't want job control
NO_JOBS=-DJOBS=0
MKB_NO_JOBS=-j
CPPFLAGS= -DSHELL -I. -D_MINIX $(EDIT) $(NO_PATHS_H) $(NO_JOBS)
CFLAGS= $(OPT) $(CPPFLAGS)
LIBS= $(EDITLIB) $(FLEXLIB)
CLEANFILES= $(OBJS) \
builtins.c builtins.h init.c mkinit mknodes mksignames mksyntax \
nodes.c nodes.h signames.c signames.h syntax.c syntax.h token.def \
arith.c arith_y.h arith_lex.c builtins.c builtins.h init.c \
mkinit mknodes mksignames mksyntax \
nodes.c nodes.h signames.c signames.h syntax.c syntax.h token.h \
bltin/operators.h bltin/operators.c
all: sh
sh: $(OBJS)
$(CC) $(CFLAGS) -o sh $(OBJS) $(LIBS)
install -S 100k sh
$(CC) $(CFLAGS) -fnone -o sh $(OBJS) $(LIBS)
install: /usr/bin/ash /usr/bin/sh /bin/sh /bin/bigsh
install: /usr/bin/ash /usr/bin/sh /bin/sh /usr/man/man1/ash.1 \
/usr/man/man1/echo.1 /usr/man/man1/expr.1
/usr/bin/ash: sh
install -cs -o bin $? $@
install -c $? $@
/usr/bin/sh: /usr/bin/ash
install -l $? $@
@ -43,8 +63,14 @@ install: /usr/bin/ash /usr/bin/sh /bin/sh /bin/bigsh
/bin/sh: /usr/bin/ash
install -lcs $? $@
/bin/bigsh: /usr/bin/ash
install -S 1500000 -lcs $? $@
/usr/man/man1/ash.1: sh.1
install -lc $? $@
/usr/man/man1/echo.1: bltin/echo.1
install -lc $? $@
/usr/man/man1/expr.1: bltin/expr.1
install -lc $? $@
clean:
rm -f $(CLEANFILES) sh core
@ -54,11 +80,18 @@ parser.o: token.def
token.def: mktokens
sh mktokens
builtins.c builtins.h: builtins.table shell.h
sh mkbuiltins shell.h builtins.table
arith.c: arith.y
$(YACC) -d $?
mv y.tab.c $@
mv y.tab.h arith_y.h
init.o: mkinit $(SRCS)
./mkinit '$(CC) -c $(CFLAGS) init.c' $(SRCS)
arith_lex.c: arith_lex.l
builtins.c builtins.h: builtins.def shell.h
sh mkbuiltins $(MKB_NO_JOBS) . shell.h builtins.def
init.c: mkinit $(SRCS)
./mkinit $(SRCS)
mkinit: mkinit.c
$(CC) $(CFLAGS) mkinit.c -o $@
@ -81,20 +114,8 @@ syntax.c syntax.h: mksyntax
mksyntax: mksyntax.c parser.h
$(CC) $(CFLAGS) mksyntax.c -o $@
bltin/operators.h: bltin/mkexpr bltin/binary_op bltin/unary_op
cd bltin && sh mkexpr
bltin/echo.o: bltin/echo.c
cd bltin && $(CC) -I.. $(CFLAGS) -c echo.c
bltin/expr.o: bltin/expr.c
cd bltin && $(CC) -I.. $(CFLAGS) -c expr.c
bltin/operators.o: bltin/operators.c
cd bltin && $(CC) -I.. $(CFLAGS) -c operators.c
bltin/regexp.o: bltin/regexp.c
cd bltin && $(CC) -I.. $(CFLAGS) -c regexp.c
bltin/operators.h: bltin/mkexpr bltin/unary_op bltin/binary_op
cd bltin && sh mkexpr unary_op binary_op
# Dependencies you say? This will have to do.
$(OBJS): error.h eval.h exec.h expand.h init.h input.h \
@ -103,3 +124,6 @@ $(OBJS): error.h eval.h exec.h expand.h init.h input.h \
builtins.h nodes.h signames.h syntax.h
bltin/expr.o bltin/operators.o: bltin/operators.h
#
# $PchId: Makefile,v 1.4 2006/05/22 12:40:46 philip Exp $

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
@ -20,7 +29,7 @@ programs is:
mknodes nodetypes nodes.h nodes.c
mksignames - signames.h signames.c
mksyntax - syntax.h syntax.c
mktokens - token.def
mktokens - token.h
bltin/mkexpr unary_op binary_op operators.h operators.c
There are undoubtedly too many of these. Mkinit searches all the
@ -346,3 +355,6 @@ cause the preprocessor can't handle functions with a variable
number of arguments. Defining DEBUG also causes the shell to
generate a core dump if it is sent a quit signal. The tracing
code is in show.c.
#
# $PchId: TOUR,v 1.3 2006/03/31 11:33:46 philip Exp $

265
commands/ash/alias.c Normal file
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
* shell. If SHELL is defined, we try to map the standard UNIX library
* routines to ash routines using defines.
*
* Copyright (C) 1989 by Kenneth Almquist. All rights reserved.
* This file is part of ash, which is distributed under the terms specified
* by the Ash General Public License. See the file named LICENSE.
*/
#include "../shell.h"
#include "../mystring.h"
#ifdef SHELL
#include "builtins.h"
#include "../output.h"
#undef stdout
#define stdout out1
#undef stderr
#define stderr out2
#define printf out1fmt
#undef putc
#define putc(c, file) outc(c, file)
#undef putchar
#define putchar(c) out1c(c)
#define fprintf outfmt
#define fputs outstr
#define fflush flushout
#define INITARGS(argv)
#define warnx1(a, b, c) { \
char buf[64]; \
(void)snprintf(buf, sizeof(buf), a); \
error("%s", buf); \
}
#define warnx2(a, b, c) { \
char buf[64]; \
(void)snprintf(buf, sizeof(buf), a, b); \
error("%s", buf); \
}
#define warnx3(a, b, c) { \
char buf[64]; \
(void)snprintf(buf, sizeof(buf), a, b, c); \
error("%s", buf); \
}
#else
#undef NULL
#include <stdio.h>
@ -28,13 +80,12 @@
#define INITARGS(argv) if ((commandname = argv[0]) == NULL) {fputs("Argc is zero\n", stderr); exit(2);} else
#endif
#ifdef __STDC__
pointer stalloc(int);
void error(char *, ...);
#else
pointer stalloc();
void error();
#endif
void error(const char *, ...);
extern char *commandname;
/*
* $PchId: bltin.h,v 1.4 2006/03/29 11:39:00 philip Exp $
*/

View file

@ -1,74 +1,126 @@
/*
* Echo command.
/*-
* Copyright (c) 1991, 1993
* The Regents of the University of California. All rights reserved.
*
* Copyright (C) 1989 by Kenneth Almquist. All rights reserved.
* This file is part of ash, which is distributed under the terms specified
* by the Ash General Public License. See the file named LICENSE.
* This code is derived from software contributed to Berkeley by
* Kenneth Almquist.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* @(#)echo.c 8.2 (Berkeley) 5/4/95
*/
#define main echocmd
/*
#include <sys/cdefs.h>
__FBSDID("$FreeBSD: src/bin/sh/bltin/echo.c,v 1.14 2004/04/06 20:06:53 markm Exp $");
*/
/*
* Echo command.
*/
#ifdef __minix
#define MINIX
#endif
#include "bltin.h"
#ifndef MINIX
/* #define eflag 1 */
#else
#undef eflag
main(argc, argv) char **argv; {
register char **ap;
register char *p;
register char c;
int count;
int nflag = 0;
#ifndef eflag
int eflag = 0;
#endif
ap = argv;
if (argc)
ap++;
if ((p = *ap) != NULL) {
if (equal(p, "--")) {
ap++;
}
if (equal(p, "-n")) {
nflag++;
ap++;
} else if (equal(p, "-e")) {
int
echocmd(argc, argv)
int argc;
char **argv;
{
char **ap;
char *p;
char c;
int count;
int nflag = 0;
#ifndef eflag
eflag++;
int eflag = 0;
#endif
ap++;
}
}
while ((p = *ap++) != NULL) {
while ((c = *p++) != '\0') {
if (c == '\\' && eflag) {
switch (*p++) {
case 'b': c = '\b'; break;
case 'c': return 0; /* exit */
case 'f': c = '\f'; break;
case 'n': c = '\n'; break;
case 'r': c = '\r'; break;
case 't': c = '\t'; break;
case 'v': c = '\v'; break;
case '\\': break; /* c = '\\' */
case '0':
c = 0;
count = 3;
while (--count >= 0 && (unsigned)(*p - '0') < 8)
c = (c << 3) + (*p++ - '0');
break;
default:
p--;
break;
ap = argv;
if (argc)
ap++;
if ((p = *ap) != NULL) {
#ifdef MINIX
if (equal(p, "--")) {
ap++;
}
#endif
if (equal(p, "-n")) {
nflag++;
ap++;
} else if (equal(p, "-e")) {
#ifndef eflag
eflag++;
#endif
ap++;
}
}
while ((p = *ap++) != NULL) {
while ((c = *p++) != '\0') {
if (c == '\\' && eflag) {
switch (*p++) {
case 'a': c = '\a'; break;
case 'b': c = '\b'; break;
case 'c': return 0; /* exit */
case 'e': c = '\033'; break;
case 'f': c = '\f'; break;
case 'n': c = '\n'; break;
case 'r': c = '\r'; break;
case 't': c = '\t'; break;
case 'v': c = '\v'; break;
case '\\': break; /* c = '\\' */
case '0':
c = 0;
count = 3;
while (--count >= 0 && (unsigned)(*p - '0') < 8)
c = (c << 3) + (*p++ - '0');
break;
default:
p--;
break;
}
}
}
putchar(c);
}
if (*ap)
putchar(' ');
}
if (! nflag)
putchar('\n');
return 0;
putchar(c);
}
if (*ap)
putchar(' ');
}
if (! nflag)
putchar('\n');
return 0;
}
/*
* $PchId: echo.c,v 1.5 2006/05/23 12:05:56 philip Exp $
*/

View file

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

View file

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

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

View file

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

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 -
#
# Copyright (c) 1991 The Regents of the University of California.
# All rights reserved.
# Copyright (c) 1991, 1993
# The Regents of the University of California. All rights reserved.
#
# This code is derived from software contributed to Berkeley by
# Kenneth Almquist.
@ -34,19 +34,21 @@
# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
# SUCH DAMAGE.
#
# @(#)builtins 5.1 (Berkeley) 3/7/91
# @(#)builtins 8.1 (Berkeley) 5/31/93
#
# This file lists all the builtin commands. The first column is the name
# of a C routine. The -j flag, if present, specifies that this command
# is to be excluded from systems without job control. The rest of the line
# specifies the command name or names used to run the command. The entry
# for nullcmd, which is run when the user does not specify a command, must
# for bltincmd, which is run when the user does not specify a command, must
# come first.
#
# Copyright (C) 1989 by Kenneth Almquist. All rights reserved.
# This file is part of ash, which is distributed under the terms specified
# by the Ash General Public License. See the file named LICENSE.
#
# NOTE: bltincmd must come first!
bltincmd command
#alloccmd alloc
@ -59,17 +61,19 @@ echocmd echo
evalcmd eval
execcmd exec
exitcmd exit
expcmd exp let
exportcmd export readonly
exprcmd expr test [
#exprcmd expr test [
histcmd fc
fgcmd -j fg
getoptscmd getopts
hashcmd hash
jobidcmd jobid
jobscmd jobs
#lccmd lc
#linecmd line
localcmd local
#nlechocmd nlecho
printfcmd printf
pwdcmd pwd
readcmd read
returncmd return
@ -77,7 +81,10 @@ setcmd set
setvarcmd setvar
shiftcmd shift
trapcmd trap
truecmd : true false
truecmd : true
umaskcmd umask
unaliascmd unalias
unsetcmd unset
waitcmd wait
#foocmd foo
aliascmd alias

94
commands/ash/builtins.def Normal file
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.
* All rights reserved.
* Copyright (c) 1991, 1993
* The Regents of the University of California. All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* Kenneth Almquist.
@ -13,10 +13,6 @@
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
@ -35,8 +31,22 @@
*/
#ifndef lint
static char sccsid[] = "@(#)cd.c 5.2 (Berkeley) 3/13/91";
#if 0
static char sccsid[] = "@(#)cd.c 8.2 (Berkeley) 5/4/95";
#endif
#endif /* not lint */
/*
#include <sys/cdefs.h>
__FBSDID("$FreeBSD: src/bin/sh/cd.c,v 1.34 2004/04/06 20:06:51 markm Exp $");
*/
#include <sys/types.h>
#include <sys/stat.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include <limits.h>
/*
* The cd and pwd commands.
@ -50,115 +60,124 @@ static char sccsid[] = "@(#)cd.c 5.2 (Berkeley) 3/13/91";
#include "output.h"
#include "memalloc.h"
#include "error.h"
#include "exec.h"
#include "redir.h"
#include "mystring.h"
#include <sys/types.h>
#include <sys/stat.h>
#include <errno.h>
#include "builtins.h"
#include "show.h"
#include "cd.h"
#ifdef __STDC__
STATIC int cdlogical(char *);
STATIC int cdphysical(char *);
STATIC int docd(char *, int, int);
STATIC void updatepwd(char *);
STATIC void getpwd(void);
STATIC char *getcomponent(void);
#else
STATIC int docd();
STATIC void updatepwd();
STATIC void getpwd();
STATIC char *getcomponent();
#endif
STATIC int updatepwd(char *);
char *curdir; /* current working directory */
STATIC char *curdir = NULL; /* current working directory */
STATIC char *prevdir; /* previous working directory */
STATIC char *cdcomppath;
#if UDIR || TILDE
extern int didudir; /* set if /u/logname or ~logname expanded */
#endif
int
cdcmd(argc, argv) char **argv; {
cdcmd(int argc, char **argv)
{
char *dest;
char *path;
char *p;
struct stat statb;
char *padvance();
int tohome= 0;
int ch, phys, print = 0;
nextopt(nullstr);
if ((dest = *argptr) == NULL) {
if ((dest = bltinlookup("HOME", 1)) == NULL)
error("HOME not set");
tohome = 1;
optreset = 1; optind = 1; opterr = 0; /* initialize getopt */
phys = Pflag;
while ((ch = getopt(argc, argv, "LP")) != -1) {
switch (ch) {
case 'L':
phys = 0;
break;
case 'P':
phys = 1;
break;
default:
error("unknown option: -%c", optopt);
break;
}
}
argc -= optind;
argv += optind;
if (argc > 1)
error("too many arguments");
if ((dest = *argv) == NULL && (dest = bltinlookup("HOME", 1)) == NULL)
error("HOME not set");
if (*dest == '\0')
dest = ".";
if (dest[0] == '-' && dest[1] == '\0') {
dest = prevdir ? prevdir : curdir;
if (dest)
print = 1;
else
dest = ".";
}
if (*dest == '/' || (path = bltinlookup("CDPATH", 1)) == NULL)
path = nullstr;
while ((p = padvance(&path, dest)) != NULL) {
if (stat(p, &statb) >= 0
&& (statb.st_mode & S_IFMT) == S_IFDIR
&& docd(p, strcmp(p, dest), tohome) >= 0)
return 0;
if (stat(p, &statb) >= 0 && S_ISDIR(statb.st_mode)) {
if (!print) {
/*
* XXX - rethink
*/
if (p[0] == '.' && p[1] == '/' && p[2] != '\0')
p += 2;
print = strcmp(p, dest);
}
if (docd(p, print, phys) >= 0)
return 0;
}
}
error("can't cd to %s", dest);
/*NOTREACHED*/
return 0;
}
/*
* Actually do the chdir. If the name refers to symbolic links, we
* compute the actual directory name before doing the cd. In an
* interactive shell, print the directory name if "print" is nonzero
* or if the name refers to a symbolic link. We also print the name
* if "/u/logname" was expanded in it, since this is similar to a
* symbolic link. (The check for this breaks if the user gives the
* cd command some additional, unused arguments.)
* Actually change the directory. In an interactive shell, print the
* directory name if "print" is nonzero.
*/
#if SYMLINKS == 0
STATIC int
docd(dest, print, tohome)
char *dest;
{
#if UDIR || TILDE
if (didudir)
print = 1;
#endif
INTOFF;
if (chdir(dest) < 0) {
INTON;
return -1;
}
updatepwd(dest);
INTON;
if (print && iflag)
out1fmt("%s\n", stackblock());
docd(char *dest, int print, int phys)
{
TRACE(("docd(\"%s\", %d, %d) called\n", dest, print, phys));
/* If logical cd fails, fall back to physical. */
if ((phys || cdlogical(dest) < 0) && cdphysical(dest) < 0)
return (-1);
if (print && iflag && curdir)
out1fmt("%s\n", curdir);
return 0;
}
#else
STATIC int
docd(dest, print, tohome)
char *dest;
{
register char *p;
register char *q;
char *symlink;
cdlogical(char *dest)
{
char *p;
char *q;
char *component;
struct stat statb;
int first;
int i;
int badstat;
TRACE(("docd(\"%s\", %d, %d) called\n", dest, print, tohome));
#if UDIR || TILDE
if (didudir)
print = 1;
#endif
top:
cdcomppath = dest;
/*
* Check each component of the path. If we find a symlink or
* something we can't stat, clear curdir to force a getcwd()
* next time we get the value of the current directory.
*/
badstat = 0;
cdcomppath = stalloc(strlen(dest) + 1);
scopy(dest, cdcomppath);
STARTSTACKSTR(p);
if (*dest == '/') {
STPUTC('/', p);
@ -166,7 +185,7 @@ top:
}
first = 1;
while ((q = getcomponent()) != NULL) {
if (q[0] == '\0' || q[0] == '.' && q[1] == '\0')
if (q[0] == '\0' || (q[0] == '.' && q[1] == '\0'))
continue;
if (! first)
STPUTC('/', p);
@ -177,71 +196,42 @@ top:
if (equal(component, ".."))
continue;
STACKSTRNUL(p);
if (lstat(stackblock(), &statb) < 0)
error("lstat %s failed", stackblock());
if ((statb.st_mode & S_IFMT) != S_IFLNK)
continue;
/* Hit a symbolic link. We have to start all over again. */
print = 1;
STPUTC('\0', p);
symlink = grabstackstr(p);
i = (int)statb.st_size + 2; /* 2 for '/' and '\0' */
if (cdcomppath != NULL)
i += strlen(cdcomppath);
p = stalloc(i);
if (readlink(symlink, p, (int)statb.st_size) < 0) {
error("readlink %s failed", stackblock());
if (lstat(stackblock(), &statb) < 0) {
badstat = 1;
break;
}
if (cdcomppath != NULL) {
p[(int)statb.st_size] = '/';
scopy(cdcomppath, p + (int)statb.st_size + 1);
} else {
p[(int)statb.st_size] = '\0';
}
if (p[0] != '/') { /* relative path name */
char *r;
q = r = symlink;
while (*q) {
if (*q++ == '/')
r = q;
}
*r = '\0';
dest = stalloc(strlen(symlink) + strlen(p) + 1);
scopy(symlink, dest);
strcat(dest, p);
} else {
dest = p;
}
goto top;
}
STPUTC('\0', p);
p = grabstackstr(p);
INTOFF;
/* The empty string is not a legal argument to chdir on a POSIX 1003.1
* system. */
if (p[0] != '\0' && chdir(p) < 0) {
if (updatepwd(badstat ? NULL : dest) < 0 || chdir(curdir) < 0) {
INTON;
return -1;
return (-1);
}
updatepwd(p);
INTON;
if (print && !tohome && iflag)
out1fmt("%s\n", p);
return 0;
return (0);
}
#endif /* SYMLINKS */
STATIC int
cdphysical(char *dest)
{
INTOFF;
if (chdir(dest) < 0 || updatepwd(NULL) < 0) {
INTON;
return (-1);
}
INTON;
return (0);
}
/*
* Get the next component of the path name pointed to by cdcomppath.
* This routine overwrites the string pointed to by cdcomppath.
*/
STATIC char *
getcomponent() {
register char *p;
getcomponent(void)
{
char *p;
char *start;
if ((p = cdcomppath) == NULL)
@ -259,29 +249,43 @@ getcomponent() {
}
/*
* Update curdir (the name of the current directory) in response to a
* cd command. We also call hashcd to let the routines in exec.c know
* that the current directory has changed.
*/
void hashcd();
STATIC void
updatepwd(dir)
char *dir;
{
STATIC int
updatepwd(char *dir)
{
char *new;
char *p;
hashcd(); /* update command hash table */
/*
* If our argument is NULL, we don't know the current directory
* any more because we traversed a symbolic link or something
* we couldn't stat().
*/
if (dir == NULL || curdir == NULL) {
if (prevdir)
ckfree(prevdir);
INTOFF;
prevdir = curdir;
curdir = NULL;
if (getpwd() == NULL) {
INTON;
return (-1);
}
setvar("PWD", curdir, VEXPORT);
setvar("OLDPWD", prevdir, VEXPORT);
INTON;
return (0);
}
cdcomppath = stalloc(strlen(dir) + 1);
scopy(dir, cdcomppath);
STARTSTACKSTR(new);
if (*dir != '/') {
if (curdir == NULL)
return;
p = curdir;
while (*p)
STPUTC(*p++, new);
@ -300,73 +304,87 @@ updatepwd(dir)
if (new == stackblock())
STPUTC('/', new);
STACKSTRNUL(new);
if (curdir)
ckfree(curdir);
INTOFF;
if (prevdir)
ckfree(prevdir);
prevdir = curdir;
curdir = savestr(stackblock());
setvar("PWD", curdir, VEXPORT);
setvar("OLDPWD", prevdir, VEXPORT);
INTON;
return (0);
}
int
pwdcmd(argc, argv) char **argv; {
getpwd();
out1str(curdir);
out1c('\n');
pwdcmd(int argc, char **argv)
{
char buf[PATH_MAX];
int ch, phys;
optreset = 1; optind = 1; opterr = 0; /* initialize getopt */
phys = Pflag;
while ((ch = getopt(argc, argv, "LP")) != -1) {
switch (ch) {
case 'L':
phys = 0;
break;
case 'P':
phys = 1;
break;
default:
error("unknown option: -%c", optopt);
break;
}
}
argc -= optind;
argv += optind;
if (argc != 0)
error("too many arguments");
if (!phys && getpwd()) {
out1str(curdir);
out1c('\n');
} else {
if (getcwd(buf, sizeof(buf)) == NULL)
error(".: %s", strerror(errno));
out1str(buf);
out1c('\n');
}
return 0;
}
/*
* Run /bin/pwd to find out what the current directory is. We suppress
* interrupts throughout most of this, but the user can still break out
* of it by killing the pwd program. If we already know the current
* Find out what the current directory is. If we already know the current
* directory, this routine returns immediately.
*/
#define MAXPWD 256
STATIC void
getpwd() {
char buf[MAXPWD];
char *p;
int i;
int status;
struct job *jp;
int pip[2];
char *
getpwd(void)
{
char buf[PATH_MAX];
if (curdir)
return;
INTOFF;
if (pipe(pip) < 0)
error("Pipe call failed");
jp = makejob((union node *)NULL, 1);
if (forkshell(jp, (union node *)NULL, FORK_NOJOB) == 0) {
close(pip[0]);
if (pip[1] != 1) {
close(1);
copyfd(pip[1], 1);
close(pip[1]);
return curdir;
if (getcwd(buf, sizeof(buf)) == NULL) {
char *pwd = getenv("PWD");
struct stat stdot, stpwd;
if (pwd && *pwd == '/' && stat(".", &stdot) != -1 &&
stat(pwd, &stpwd) != -1 &&
stdot.st_dev == stpwd.st_dev &&
stdot.st_ino == stpwd.st_ino) {
curdir = savestr(pwd);
return curdir;
}
execl("/bin/pwd", "pwd", (char *)0);
error("Cannot exec /bin/pwd");
return NULL;
}
close(pip[1]);
pip[1] = -1;
p = buf;
while ((i = read(pip[0], p, buf + MAXPWD - p)) > 0
|| i == -1 && errno == EINTR) {
if (i > 0)
p += i;
}
close(pip[0]);
pip[0] = -1;
status = waitforjob(jp);
if (status != 0)
error((char *)0);
if (i < 0 || p == buf || p[-1] != '\n')
error("pwd command failed");
p[-1] = '\0';
curdir = savestr(buf);
INTON;
return curdir;
}
/*
* $PchId: cd.c,v 1.6 2006/05/22 12:42:03 philip Exp $
*/

38
commands/ash/cd.h Normal file
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.
* All rights reserved.
* Copyright (c) 1991, 1993
* The Regents of the University of California. All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* Kenneth Almquist.
@ -13,10 +13,6 @@
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
@ -35,8 +31,14 @@
*/
#ifndef lint
static char sccsid[] = "@(#)error.c 5.1 (Berkeley) 3/7/91";
#if 0
static char sccsid[] = "@(#)error.c 8.2 (Berkeley) 5/4/95";
#endif
#endif /* not lint */
/*
#include <sys/cdefs.h>
__FBSDID("$FreeBSD: src/bin/sh/error.c,v 1.25 2004/04/06 20:06:51 markm Exp $");
*/
/*
* Errors and exceptions.
@ -47,14 +49,14 @@ static char sccsid[] = "@(#)error.c 5.1 (Berkeley) 3/7/91";
#include "options.h"
#include "output.h"
#include "error.h"
#include <sys/types.h>
#include "nodes.h" /* show.h needs nodes.h */
#include "show.h"
#include "trap.h"
#include <signal.h>
#ifdef __STDC__
#include "stdarg.h"
#else
#include <varargs.h>
#endif
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <sys/types.h>
/*
@ -62,12 +64,14 @@ static char sccsid[] = "@(#)error.c 5.1 (Berkeley) 3/7/91";
*/
struct jmploc *handler;
int exception;
volatile int suppressint;
volatile int intpending;
volatile sig_atomic_t exception;
volatile sig_atomic_t suppressint;
volatile sig_atomic_t intpending;
char *commandname;
static void exverror(int, const char *, va_list) __printf0like(2, 0);
/*
* Called to raise an exception. Since C doesn't include exceptions, we
* just do a longjmp to the exception handler. The type of exception is
@ -75,7 +79,8 @@ char *commandname;
*/
void
exraise(e) {
exraise(int e)
{
if (handler == NULL)
abort();
exception = e;
@ -87,69 +92,63 @@ exraise(e) {
* Called from trap.c when a SIGINT is received. (If the user specifies
* that SIGINT is to be trapped or ignored using the trap builtin, then
* this routine is not called.) Suppressint is nonzero when interrupts
* are held using the INTOFF macro. The call to _exit is necessary because
* there is a short period after a fork before the signal handlers are
* set to the appropriate value for the child. (The test for iflag is
* just defensive programming.)
* are held using the INTOFF macro. If SIGINTs are not suppressed and
* the shell is not a root shell, then we want to be terminated if we
* get here, as if we were terminated directly by a SIGINT. Arrange for
* this here.
*/
void
onint() {
if (suppressint) {
onint(void)
{
sigset_t sigset;
/*
* The !in_dotrap here is safe. The only way we can arrive here
* with in_dotrap set is that a trap handler set SIGINT to SIG_DFL
* and killed itself.
*/
if (suppressint && !in_dotrap) {
intpending++;
return;
}
intpending = 0;
#ifdef BSD
sigsetmask(0);
sigemptyset(&sigset);
sigprocmask(SIG_SETMASK, &sigset, NULL);
/*
* This doesn't seem to be needed, since main() emits a newline.
*/
#if 0
if (tcgetpgrp(0) == getpid())
write(STDERR_FILENO, "\n", 1);
#endif
if (rootshell && iflag)
exraise(EXINT);
else
_exit(128 + SIGINT);
}
void
error2(a, b)
char *a, *b;
{
error("%s: %s", a, b);
else {
signal(SIGINT, SIG_DFL);
kill(getpid(), SIGINT);
}
}
/*
* Error is called to raise the error exception. If the first argument
* Exverror is called to raise the error exception. If the first argument
* is not NULL then error prints an error message using printf style
* formatting. It then raises the error exception.
*/
#ifdef __STDC__
void
error(char *msg, ...) {
#else
void
error(va_alist)
va_dcl
{
char *msg;
#endif
va_list ap;
static void
exverror(int cond, const char *msg, va_list ap)
{
CLEAR_PENDING_INT;
INTOFF;
#ifdef __STDC__
va_start(ap, msg);
#else
va_start(ap);
msg = va_arg(ap, char *);
#endif
#if DEBUG
if (msg)
TRACE(("error(\"%s\") pid=%d\n", msg, getpid()));
TRACE(("exverror(%d, \"%s\") pid=%d\n", cond, msg, getpid()));
else
TRACE(("error(NULL) pid=%d\n", getpid()));
TRACE(("exverror(%d, NULL) pid=%d\n", cond, getpid()));
#endif
if (msg) {
if (commandname)
@ -157,96 +156,30 @@ error(va_alist)
doformat(&errout, msg, ap);
out2c('\n');
}
va_end(ap);
flushall();
exraise(EXERROR);
exraise(cond);
}
#ifdef notdef /* These strange error messages only confuse. -- kjb */
/*
* Table of error messages.
*/
struct errname {
short errcode; /* error number */
short action; /* operation which encountered the error */
char *msg; /* text describing the error */
};
#define ALL (E_OPEN|E_CREAT|E_EXEC)
STATIC const struct errname errormsg[] = {
EINTR, ALL, "interrupted",
EACCES, ALL, "permission denied",
EIO, ALL, "I/O error",
ENOENT, E_OPEN, "no such file",
ENOENT, E_CREAT, "directory nonexistent",
ENOENT, E_EXEC, "not found",
ENOTDIR, E_OPEN, "no such file",
ENOTDIR, E_CREAT, "directory nonexistent",
ENOTDIR, E_EXEC, "not found",
ENOEXEC, ALL, "not an executable",
EISDIR, ALL, "is a directory",
/* EMFILE, ALL, "too many open files", */
ENFILE, ALL, "file table overflow",
ENOSPC, ALL, "file system full",
#ifdef EDQUOT
EDQUOT, ALL, "disk quota exceeded",
#endif
#ifdef ENOSR
ENOSR, ALL, "no streams resources",
#endif
ENXIO, ALL, "no such device or address",
EROFS, ALL, "read-only file system",
ETXTBSY, ALL, "text busy",
#ifdef SYSV
EAGAIN, E_EXEC, "not enough memory",
#endif
ENOMEM, ALL, "not enough memory",
#ifdef ENOLINK
ENOLINK, ALL, "remote access failed",
#endif
#ifdef EMULTIHOP
EMULTIHOP, ALL, "remote access failed",
#endif
#ifdef ECOMM
ECOMM, ALL, "remote access failed",
#endif
#ifdef ESTALE
ESTALE, ALL, "remote access failed",
#endif
#ifdef ETIMEDOUT
ETIMEDOUT, ALL, "remote access failed",
#endif
#ifdef ELOOP
ELOOP, ALL, "symbolic link loop",
#endif
E2BIG, E_EXEC, "argument list too long",
#ifdef ELIBACC
ELIBACC, E_EXEC, "shared library missing",
#endif
0, 0, NULL
};
/*
* Return a string describing an error. The returned string may be a
* pointer to a static buffer that will be overwritten on the next call.
* Action describes the operation that got the error.
*/
char *
errmsg(e, action) {
const struct errname *ep;
static char buf[12];
for (ep = errormsg ; ep->errcode ; ep++) {
if (ep->errcode == e && (ep->action & action) != 0)
return ep->msg;
}
fmtstr(buf, sizeof buf, "error %d", e);
return buf;
void
error(const char *msg, ...)
{
va_list ap;
va_start(ap, msg);
exverror(EXERROR, msg, ap);
va_end(ap);
}
#endif
void
exerror(int cond, const char *msg, ...)
{
va_list ap;
va_start(ap, msg);
exverror(cond, msg, ap);
va_end(ap);
}
/*
* $PchId: error.c,v 1.5 2006/04/10 14:36:23 philip Exp $
*/

View file

@ -1,6 +1,6 @@
/*-
* Copyright (c) 1991 The Regents of the University of California.
* All rights reserved.
* Copyright (c) 1991, 1993
* The Regents of the University of California. All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* Kenneth Almquist.
@ -13,10 +13,6 @@
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
@ -33,41 +29,35 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* @(#)error.h 5.1 (Berkeley) 3/7/91
* @(#)error.h 8.2 (Berkeley) 5/4/95
* $FreeBSD: src/bin/sh/error.h,v 1.17 2004/04/06 20:06:51 markm Exp $
*/
/*
* Types of operations (passed to the errmsg routine).
*/
#define E_OPEN 01 /* opening a file */
#define E_CREAT 02 /* creating a file */
#define E_EXEC 04 /* executing a program */
/*
* We enclose jmp_buf in a structure so that we can declare pointers to
* jump locations. The global variable handler contains the location to
* jump to when an exception occurs, and the global variable exception
* contains a code identifying the exeception. To implement nested
* contains a code identifying the exception. To implement nested
* exception handlers, the user should save the value of handler on entry
* to an inner scope, set handler to point to a jmploc structure for the
* inner scope, and restore handler on exit from the scope.
*/
#include <setjmp.h>
#include <signal.h>
struct jmploc {
jmp_buf loc;
};
extern struct jmploc *handler;
extern int exception;
extern volatile sig_atomic_t exception;
/* exceptions */
#define EXINT 0 /* SIGINT received */
#define EXERROR 1 /* a generic error */
#define EXSHELLPROC 2 /* execute a shell procedure */
#define EXEXEC 3 /* command execution failed */
/*
@ -77,32 +67,21 @@ extern int exception;
* more fun than worrying about efficiency and portability. :-))
*/
extern volatile int suppressint;
extern volatile int intpending;
extern char *commandname; /* name of command--printed on error */
extern volatile sig_atomic_t suppressint;
extern volatile sig_atomic_t intpending;
#define INTOFF suppressint++
#define INTON if (--suppressint == 0 && intpending) onint(); else
#define INTON { if (--suppressint == 0 && intpending) onint(); }
#define FORCEINTON {suppressint = 0; if (intpending) onint();}
#define CLEAR_PENDING_INT intpending = 0
#define int_pending() intpending
#ifdef __STDC__
#define __printf0like(a,b)
void exraise(int);
void onint(void);
void error2(char *, char *);
void error(char *, ...);
char *errmsg(int, int);
#else
void exraise();
void onint();
void error2();
void error();
char *errmsg();
#endif
/* Errmsg uses confusingly different messages. Prefer strerror(). -- kjb */
#define errmsg(errno, action) strerror(errno)
void error(const char *, ...) __printf0like(1, 2);
void exerror(int, const char *, ...) __printf0like(2, 3);
/*
@ -111,6 +90,12 @@ char *errmsg();
*/
#ifdef BSD
#ifndef __minix
#define setjmp(jmploc) _setjmp(jmploc)
#define longjmp(jmploc, val) _longjmp(jmploc, val)
#endif
#endif
/*
* $PchId: error.h,v 1.5 2006/04/10 14:36:43 philip Exp $
*/

View file

@ -1,6 +1,6 @@
/*-
* Copyright (c) 1991 The Regents of the University of California.
* All rights reserved.
* Copyright (c) 1993
* The Regents of the University of California. All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* Kenneth Almquist.
@ -13,10 +13,6 @@
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
@ -35,8 +31,23 @@
*/
#ifndef lint
static char sccsid[] = "@(#)eval.c 5.3 (Berkeley) 4/12/91";
#if 0
static char sccsid[] = "@(#)eval.c 8.9 (Berkeley) 6/8/95";
#endif
#endif /* not lint */
/*
#include <sys/cdefs.h>
__FBSDID("$FreeBSD: src/bin/sh/eval.c,v 1.42 2004/04/06 20:06:51 markm Exp $");
*/
#ifndef NO_PATHS_H
#include <paths.h>
#endif
#include <signal.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/wait.h> /* For WIFSIGNALED(status) */
#include <errno.h>
/*
* Evaluate a command.
@ -59,22 +70,21 @@ static char sccsid[] = "@(#)eval.c 5.3 (Berkeley) 4/12/91";
#include "var.h"
#include "memalloc.h"
#include "error.h"
#include "show.h"
#include "mystring.h"
#include <sys/types.h>
#include <signal.h>
#if !defined(NO_HISTORY) && !defined(EDITLINE)
#include "myhistedit.h"
#endif
#ifndef _PATH_STDPATH
#define _PATH_STDPATH "/usr/bin:/bin:/usr/sbin:/sbin:"
#endif
/* flags in argument to evaltree */
#define EV_EXIT 01 /* exit after evaluating tree */
#define EV_TESTED 02 /* exit status is checked; ignore -e flag */
#define EV_BACKCMD 04 /* command executing within back quotes */
/* reasons for skipping commands (see comment on breakcmd routine) */
#define SKIPBREAK 1
#define SKIPCONT 2
#define SKIPFUNC 3
MKINIT int evalskip; /* set if we are skipping commands */
STATIC int skipcount; /* number of levels to skip */
MKINIT int loopnest; /* current loop nesting level */
@ -87,7 +97,6 @@ int exitstatus; /* exit status of last command */
int oexitstatus; /* saved exit status */
#ifdef __STDC__
STATIC void evalloop(union node *);
STATIC void evalfor(union node *);
STATIC void evalcase(union node *, int);
@ -96,17 +105,6 @@ STATIC void expredir(union node *);
STATIC void evalpipe(union node *);
STATIC void evalcommand(union node *, int, struct backcmd *);
STATIC void prehash(union node *);
#else
STATIC void evalloop();
STATIC void evalfor();
STATIC void evalcase();
STATIC void evalsubshell();
STATIC void expredir();
STATIC void evalpipe();
STATIC void evalcommand();
STATIC void prehash();
#endif
/*
@ -130,11 +128,11 @@ SHELLPROC {
/*
* The eval commmand.
* The eval command.
*/
evalcmd(argc, argv)
char **argv;
int
evalcmd(int argc, char **argv)
{
char *p;
char *concat;
@ -166,9 +164,8 @@ evalcmd(argc, argv)
*/
void
evalstring(s)
char *s;
{
evalstring(char *s)
{
union node *n;
struct stackmark smark;
@ -190,14 +187,17 @@ evalstring(s)
*/
void
evaltree(n, flags)
union node *n;
{
evaltree(union node *n, int flags)
{
if (n == NULL) {
TRACE(("evaltree(NULL) called\n"));
return;
exitstatus = 0;
goto out;
}
TRACE(("evaltree(0x%x: %d) called\n", (int)n, n->type));
#if !defined(NO_HISTORY) && !defined(EDITLINE)
displayhist = 1; /* show history substitutions done with fc */
#endif
TRACE(("evaltree(0x%lx: %d) called\n", (long)n, n->type));
switch (n->type) {
case NSEMI:
evaltree(n->nbinary.ch1, 0);
@ -207,8 +207,9 @@ evaltree(n, flags)
break;
case NAND:
evaltree(n->nbinary.ch1, EV_TESTED);
if (evalskip || exitstatus != 0)
if (evalskip || exitstatus != 0) {
goto out;
}
evaltree(n->nbinary.ch2, flags);
break;
case NOR:
@ -230,19 +231,15 @@ evaltree(n, flags)
evalsubshell(n, flags);
break;
case NIF: {
int status = 0;
evaltree(n->nif.test, EV_TESTED);
if (evalskip)
goto out;
if (exitstatus == 0) {
if (exitstatus == 0)
evaltree(n->nif.ifpart, flags);
status = exitstatus;
} else if (n->nif.elsepart) {
else if (n->nif.elsepart)
evaltree(n->nif.elsepart, flags);
status = exitstatus;
}
exitstatus = status;
else
exitstatus = 0;
break;
}
case NWHILE:
@ -259,6 +256,11 @@ evaltree(n, flags)
defun(n->narg.text, n->narg.next);
exitstatus = 0;
break;
case NNOT:
evaltree(n->nnot.com, EV_TESTED);
exitstatus = !exitstatus;
break;
case NPIPE:
evalpipe(n);
break;
@ -273,18 +275,16 @@ evaltree(n, flags)
out:
if (pendingsigs)
dotrap();
if ((flags & EV_EXIT) || (eflag && exitstatus
&& !(flags & EV_TESTED) && (n->type == NCMD ||
n->type == NSUBSHELL))) {
if ((flags & EV_EXIT) || (eflag && exitstatus
&& !(flags & EV_TESTED) && (n->type == NCMD ||
n->type == NSUBSHELL)))
exitshell(exitstatus);
}
}
STATIC void
evalloop(n)
union node *n;
{
evalloop(union node *n)
{
int status;
loopnest++;
@ -319,9 +319,8 @@ skipping: if (evalskip == SKIPCONT && --skipcount <= 0) {
STATIC void
evalfor(n)
union node *n;
{
evalfor(union node *n)
{
struct arglist arglist;
union node *argp;
struct strlist *sp;
@ -331,7 +330,7 @@ evalfor(n)
arglist.lastp = &arglist.list;
for (argp = n->nfor.args ; argp ; argp = argp->narg.next) {
oexitstatus = exitstatus;
expandarg(argp, &arglist, 1);
expandarg(argp, &arglist, EXP_FULL | EXP_TILDE);
if (evalskip)
goto out;
}
@ -360,9 +359,8 @@ out:
STATIC void
evalcase(n, flags)
union node *n;
{
evalcase(union node *n, int flags)
{
union node *cp;
union node *patp;
struct arglist arglist;
@ -370,8 +368,8 @@ evalcase(n, flags)
setstackmark(&smark);
arglist.lastp = &arglist.list;
oexitstatus = exitstatus;
expandarg(n->ncase.expr, &arglist, 0);
oexitstatus = exitstatus;
expandarg(n->ncase.expr, &arglist, EXP_TILDE);
for (cp = n->ncase.cases ; cp && evalskip == 0 ; cp = cp->nclist.next) {
for (patp = cp->nclist.pattern ; patp ; patp = patp->narg.next) {
if (casematch(patp, arglist.list->text)) {
@ -393,9 +391,8 @@ out:
*/
STATIC void
evalsubshell(n, flags)
union node *n;
{
evalsubshell(union node *n, int flags)
{
struct job *jp;
int backgnd = (n->type == NBACKGND);
@ -409,7 +406,7 @@ evalsubshell(n, flags)
}
if (! backgnd) {
INTOFF;
exitstatus = waitforjob(jp);
exitstatus = waitforjob(jp, (int *)NULL);
INTON;
}
}
@ -421,20 +418,30 @@ evalsubshell(n, flags)
*/
STATIC void
expredir(n)
union node *n;
{
register union node *redir;
expredir(union node *n)
{
union node *redir;
for (redir = n ; redir ; redir = redir->nfile.next) {
struct arglist fn;
fn.lastp = &fn.list;
oexitstatus = exitstatus;
if (redir->type == NFROM
|| redir->type == NTO
|| redir->type == NAPPEND) {
struct arglist fn;
fn.lastp = &fn.list;
expandarg(redir->nfile.fname, &fn, 0);
switch (redir->type) {
case NFROM:
case NTO:
case NFROMTO:
case NAPPEND:
case NCLOBBER:
expandarg(redir->nfile.fname, &fn, EXP_TILDE | EXP_REDIR);
redir->nfile.expfname = fn.list->text;
break;
case NFROMFD:
case NTOFD:
if (redir->ndup.vname) {
expandarg(redir->ndup.vname, &fn, EXP_FULL | EXP_TILDE);
fixredir(redir, fn.list->text, 1);
}
break;
}
}
}
@ -449,16 +456,15 @@ expredir(n)
*/
STATIC void
evalpipe(n)
union node *n;
{
evalpipe(union node *n)
{
struct job *jp;
struct nodelist *lp;
int pipelen;
int prevfd;
int pip[2];
TRACE(("evalpipe(0x%x) called\n", (int)n));
TRACE(("evalpipe(0x%lx) called\n", (long)n));
pipelen = 0;
for (lp = n->npipe.cmdlist ; lp ; lp = lp->next)
pipelen++;
@ -471,21 +477,20 @@ evalpipe(n)
if (lp->next) {
if (pipe(pip) < 0) {
close(prevfd);
error("Pipe call failed");
error("Pipe call failed: %s", strerror(errno));
}
}
if (forkshell(jp, lp->n, n->npipe.backgnd) == 0) {
INTON;
if (prevfd > 0) {
close(0);
copyfd(prevfd, 0);
dup2(prevfd, 0);
close(prevfd);
}
if (pip[1] >= 0) {
close(pip[0]);
if (!(prevfd >= 0 && pip[0] == 0))
close(pip[0]);
if (pip[1] != 1) {
close(1);
copyfd(pip[1], 1);
dup2(pip[1], 1);
close(pip[1]);
}
}
@ -499,7 +504,7 @@ evalpipe(n)
INTON;
if (n->npipe.backgnd == 0) {
INTOFF;
exitstatus = waitforjob(jp);
exitstatus = waitforjob(jp, (int *)NULL);
TRACE(("evalpipe: job done exit status %d\n", exitstatus));
INTON;
}
@ -515,10 +520,8 @@ evalpipe(n)
*/
void
evalbackcmd(n, result)
union node *n;
struct backcmd *result;
{
evalbackcmd(union node *n, struct backcmd *result)
{
int pip[2];
struct job *jp;
struct stackmark smark; /* unnecessary */
@ -529,21 +532,22 @@ evalbackcmd(n, result)
result->nleft = 0;
result->jp = NULL;
if (n == NULL) {
/* `` */
} else
exitstatus = 0;
goto out;
}
if (n->type == NCMD) {
exitstatus = oexitstatus;
exitstatus = oexitstatus;
evalcommand(n, EV_BACKCMD, result);
} else {
exitstatus = 0;
if (pipe(pip) < 0)
error("Pipe call failed");
error("Pipe call failed: %s", strerror(errno));
jp = makejob(n, 1);
if (forkshell(jp, n, FORK_NOJOB) == 0) {
FORCEINTON;
close(pip[0]);
if (pip[1] != 1) {
close(1);
copyfd(pip[1], 1);
dup2(pip[1], 1);
close(pip[1]);
}
evaltree(n, EV_EXIT);
@ -552,8 +556,9 @@ evalbackcmd(n, result)
result->fd = pip[0];
result->jp = jp;
}
out:
popstackmark(&smark);
TRACE(("evalbackcmd done: fd=%d buf=0x%x nleft=%d jp=0x%x\n",
TRACE(("evalbackcmd done: fd=%d buf=%p nleft=%d jp=%p\n",
result->fd, result->buf, result->nleft, result->jp));
}
@ -564,10 +569,8 @@ evalbackcmd(n, result)
*/
STATIC void
evalcommand(cmd, flags, backcmd)
union node *cmd;
struct backcmd *backcmd;
{
evalcommand(union node *cmd, int flags, struct backcmd *backcmd)
{
struct stackmark smark;
union node *argp;
struct arglist arglist;
@ -577,7 +580,6 @@ evalcommand(cmd, flags, backcmd)
char **envp;
int varflag;
struct strlist *sp;
register char *p;
int mode;
int pip[2];
struct cmdentry cmdentry;
@ -589,27 +591,38 @@ evalcommand(cmd, flags, backcmd)
struct localvar *volatile savelocalvars;
volatile int e;
char *lastarg;
int realstatus;
int do_clearcmdentry;
#if __GNUC__
/* Avoid longjmp clobbering */
(void) &argv;
(void) &argc;
(void) &lastarg;
(void) &flags;
(void) &do_clearcmdentry;
#endif
/* First expand the arguments. */
TRACE(("evalcommand(0x%x, %d) called\n", (int)cmd, flags));
TRACE(("evalcommand(0x%lx, %d) called\n", (long)cmd, flags));
setstackmark(&smark);
arglist.lastp = &arglist.list;
varlist.lastp = &varlist.list;
varflag = 1;
oexitstatus = exitstatus;
do_clearcmdentry = 0;
oexitstatus = exitstatus;
exitstatus = 0;
for (argp = cmd->ncmd.args ; argp ; argp = argp->narg.next) {
p = argp->narg.text;
char *p = argp->narg.text;
if (varflag && is_name(*p)) {
do {
p++;
} while (is_in_name(*p));
if (*p == '=') {
expandarg(argp, &varlist, 0);
expandarg(argp, &varlist, EXP_VARTILDE);
continue;
}
}
expandarg(argp, &arglist, 1);
expandarg(argp, &arglist, EXP_FULL | EXP_TILDE);
varflag = 0;
}
*arglist.lastp = NULL;
@ -619,8 +632,11 @@ evalcommand(cmd, flags, backcmd)
for (sp = arglist.list ; sp ; sp = sp->next)
argc++;
argv = stalloc(sizeof (char *) * (argc + 1));
for (sp = arglist.list ; sp ; sp = sp->next)
for (sp = arglist.list ; sp ; sp = sp->next) {
TRACE(("evalcommand arg: %s\n", sp->text));
*argv++ = sp->text;
}
*argv = NULL;
lastarg = NULL;
if (iflag && funcnest == 0 && argc > 0)
@ -628,7 +644,7 @@ evalcommand(cmd, flags, backcmd)
argv -= argc;
/* Print the command if xflag is set. */
if (xflag == 1) {
if (xflag) {
outc('+', &errout);
for (sp = varlist.list ; sp ; sp = sp->next) {
outc(' ', &errout);
@ -647,11 +663,42 @@ evalcommand(cmd, flags, backcmd)
cmdentry.cmdtype = CMDBUILTIN;
cmdentry.u.index = BLTINCMD;
} else {
find_command(argv[0], &cmdentry, 1);
static const char PATH[] = "PATH=";
char *path = pathval();
/*
* Modify the command lookup path, if a PATH= assignment
* is present
*/
for (sp = varlist.list ; sp ; sp = sp->next)
if (strncmp(sp->text, PATH, sizeof(PATH) - 1) == 0) {
path = sp->text + sizeof(PATH) - 1;
/*
* On `PATH=... command`, we need to make
* sure that the command isn't using the
* non-updated hash table of the outer PATH
* setting and we need to make sure that
* the hash table isn't filled with items
* from the temporary setting.
*
* It would be better to forbit using and
* updating the table while this command
* runs, by the command finding mechanism
* is heavily integrated with hash handling,
* so we just delete the hash before and after
* the command runs. Partly deleting like
* changepatch() does doesn't seem worth the
* bookinging effort, since most such runs add
* directories in front of the new PATH.
*/
clearcmdentry(0);
do_clearcmdentry = 1;
}
find_command(argv[0], &cmdentry, 1, path);
if (cmdentry.cmdtype == CMDUNKNOWN) { /* command not found */
exitstatus = 2;
exitstatus = 127;
flushout(&errout);
popstackmark(&smark);
return;
}
/* implement the bltin builtin here */
@ -662,9 +709,8 @@ evalcommand(cmd, flags, backcmd)
break;
if ((cmdentry.u.index = find_builtin(*argv)) < 0) {
outfmt(&errout, "%s: not found\n", *argv);
exitstatus = 2;
exitstatus = 127;
flushout(&errout);
popstackmark(&smark);
return;
}
if (cmdentry.u.index != BLTINCMD)
@ -675,17 +721,21 @@ evalcommand(cmd, flags, backcmd)
/* Fork off a child process if necessary. */
if (cmd->ncmd.backgnd
|| cmdentry.cmdtype == CMDNORMAL && (flags & EV_EXIT) == 0
|| (flags & EV_BACKCMD) != 0
|| (cmdentry.cmdtype == CMDNORMAL
&& ((flags & EV_EXIT) == 0 || Tflag))
|| ((flags & EV_BACKCMD) != 0
&& (cmdentry.cmdtype != CMDBUILTIN
|| cmdentry.u.index == CDCMD
|| cmdentry.u.index == DOTCMD
|| cmdentry.u.index == EVALCMD)) {
|| cmdentry.u.index == EVALCMD))
|| (cmdentry.cmdtype == CMDBUILTIN &&
cmdentry.u.index == COMMANDCMD)) {
jp = makejob(cmd, 1);
mode = cmd->ncmd.backgnd;
if (flags & EV_BACKCMD) {
mode = FORK_NOJOB;
if (pipe(pip) < 0)
error("Pipe call failed");
error("Pipe call failed: %s", strerror(errno));
}
if (forkshell(jp, cmd, mode) != 0)
goto parent; /* at end of routine */
@ -693,8 +743,7 @@ evalcommand(cmd, flags, backcmd)
FORCEINTON;
close(pip[0]);
if (pip[1] != 1) {
close(1);
copyfd(pip[1], 1);
dup2(pip[1], 1);
close(pip[1]);
}
}
@ -704,10 +753,13 @@ evalcommand(cmd, flags, backcmd)
/* This is the child process if a fork occurred. */
/* Execute the command. */
if (cmdentry.cmdtype == CMDFUNCTION) {
#if DEBUG
trputs("Shell function: "); trargs(argv);
#endif
redirect(cmd->ncmd.redirect, REDIR_PUSH);
saveparam = shellparam;
shellparam.malloc = 0;
shellparam.reset = 1;
shellparam.nparam = argc - 1;
shellparam.p = argv + 1;
shellparam.optnext = NULL;
@ -752,7 +804,9 @@ evalcommand(cmd, flags, backcmd)
if (flags & EV_EXIT)
exitshell(exitstatus);
} else if (cmdentry.cmdtype == CMDBUILTIN) {
#if DEBUG
trputs("builtin command: "); trargs(argv);
#endif
mode = (cmdentry.u.index == EXECCMD)? 0 : REDIR_PUSH;
if (flags == EV_BACKCMD) {
memout.nleft = 0;
@ -777,6 +831,7 @@ evalcommand(cmd, flags, backcmd)
exitstatus = (*builtinfunc[cmdentry.u.index])(argc, argv);
flushall();
cmddone:
cmdenviron = NULL;
out1 = &output;
out2 = &errout;
freestdout();
@ -788,10 +843,15 @@ cmddone:
}
handler = savehandler;
if (e != -1) {
if (e != EXERROR || cmdentry.u.index == BLTINCMD
|| cmdentry.u.index == DOTCMD
|| cmdentry.u.index == EVALCMD
|| cmdentry.u.index == EXECCMD)
if ((e != EXERROR && e != EXEXEC)
|| cmdentry.u.index == BLTINCMD
|| cmdentry.u.index == DOTCMD
|| cmdentry.u.index == EVALCMD
#ifndef NO_HISTORY
|| cmdentry.u.index == HISTCMD
#endif
|| cmdentry.u.index == EXECCMD
|| cmdentry.u.index == COMMANDCMD)
exraise(e);
FORCEINTON;
}
@ -803,19 +863,15 @@ cmddone:
memout.buf = NULL;
}
} else {
#if DEBUG
trputs("normal command: "); trargs(argv);
#endif
clearredir();
redirect(cmd->ncmd.redirect, 0);
if (varlist.list) {
p = stalloc(strlen(pathval()) + 1);
scopy(pathval(), p);
} else {
p = pathval();
}
for (sp = varlist.list ; sp ; sp = sp->next)
setvareq(sp->text, VEXPORT|VSTACK);
envp = environment();
shellexec(argv, envp, p, cmdentry.u.index);
shellexec(argv, envp, pathval(), cmdentry.u.index);
/*NOTREACHED*/
}
goto out;
@ -823,8 +879,12 @@ cmddone:
parent: /* parent process gets here (if we forked) */
if (mode == 0) { /* argument to fork */
INTOFF;
exitstatus = waitforjob(jp);
exitstatus = waitforjob(jp, &realstatus);
INTON;
if (iflag && loopnest > 0 && WIFSIGNALED(realstatus)) {
evalskip = SKIPBREAK;
skipcount = loopnest;
}
} else if (mode == 2) {
backcmd->fd = pip[0];
close(pip[1]);
@ -834,6 +894,8 @@ parent: /* parent process gets here (if we forked) */
out:
if (lastarg)
setvar("_", lastarg, 0);
if (do_clearcmdentry)
clearcmdentry(0);
popstackmark(&smark);
}
@ -847,13 +909,14 @@ out:
*/
STATIC void
prehash(n)
union node *n;
{
prehash(union node *n)
{
struct cmdentry entry;
if (n->type == NCMD && goodname(n->ncmd.args->narg.text))
find_command(n->ncmd.args->narg.text, &entry, 0);
if (n->type == NCMD && n->ncmd.args)
if (goodname(n->ncmd.args->narg.text))
find_command(n->ncmd.args->narg.text, &entry, 0,
pathval());
}
@ -868,8 +931,14 @@ prehash(n)
* specified variables.
*/
bltincmd(argc, argv) char **argv; {
int
bltincmd(int argc __unused, char **argv __unused)
{
listsetvar(cmdenviron);
/*
* Preserve exitstatus of a previous possible redirection
* as POSIX mandates
*/
return exitstatus;
}
@ -885,12 +954,11 @@ bltincmd(argc, argv) char **argv; {
* in the standard shell so we don't make it one here.
*/
breakcmd(argc, argv) char **argv; {
int n;
int
breakcmd(int argc, char **argv)
{
int n = argc > 1 ? number(argv[1]) : 1;
n = 1;
if (argc > 1)
n = number(argv[1]);
if (n > loopnest)
n = loopnest;
if (n > 0) {
@ -900,40 +968,108 @@ breakcmd(argc, argv) char **argv; {
return 0;
}
/*
* The `command' command.
*/
int
commandcmd(int argc, char **argv)
{
static char stdpath[] = _PATH_STDPATH;
struct jmploc loc, *old;
struct strlist *sp;
char *path;
int ch;
for (sp = cmdenviron; sp ; sp = sp->next)
setvareq(sp->text, VEXPORT|VSTACK);
path = pathval();
optind = optreset = 1;
opterr = 0;
while ((ch = getopt(argc, argv, "p")) != -1) {
switch (ch) {
case 'p':
path = stdpath;
break;
case '?':
default:
error("unknown option: -%c", optopt);
}
}
argc -= optind;
argv += optind;
if (argc != 0) {
old = handler;
handler = &loc;
if (setjmp(handler->loc) == 0)
shellexec(argv, environment(), path, 0);
handler = old;
if (exception == EXEXEC)
exit(exerrno);
exraise(exception);
}
/*
* Do nothing successfully if no command was specified;
* ksh also does this.
*/
exit(0);
}
/*
* The return command.
*/
returncmd(argc, argv) char **argv; {
int ret;
int
returncmd(int argc, char **argv)
{
int ret = argc > 1 ? number(argv[1]) : oexitstatus;
ret = oexitstatus;
if (argc > 1)
ret = number(argv[1]);
if (funcnest) {
evalskip = SKIPFUNC;
skipcount = 1;
} else {
/* skip the rest of the file */
evalskip = SKIPFILE;
skipcount = 1;
}
return ret;
}
truecmd(argc, argv) char **argv; {
return strcmp(argv[0], "false") == 0 ? 1 : 0;
int
falsecmd(int argc __unused, char **argv __unused)
{
return 1;
}
execcmd(argc, argv) char **argv; {
int
truecmd(int argc __unused, char **argv __unused)
{
return 0;
}
int
execcmd(int argc, char **argv)
{
if (argc > 1) {
struct strlist *sp;
iflag = 0; /* exit on error */
setinteractive(0);
#if JOBS
jflag = 0;
setjobctl(0);
#endif
mflag = 0;
optschanged();
for (sp = cmdenviron; sp ; sp = sp->next)
setvareq(sp->text, VEXPORT|VSTACK);
shellexec(argv + 1, environment(), pathval(), 0);
}
return 0;
}
/*
* $PchId: eval.c,v 1.7 2006/04/10 14:46:14 philip Exp $
*/

View file

@ -1,6 +1,6 @@
/*-
* Copyright (c) 1991 The Regents of the University of California.
* All rights reserved.
* Copyright (c) 1991, 1993
* The Regents of the University of California. All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* Kenneth Almquist.
@ -13,10 +13,6 @@
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
@ -33,7 +29,8 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* @(#)eval.h 5.2 (Berkeley) 4/12/91
* @(#)eval.h 8.2 (Berkeley) 5/4/95
* $FreeBSD: src/bin/sh/eval.h,v 1.10 2004/04/06 20:06:51 markm Exp $
*/
extern char *commandname; /* currently executing command */
@ -48,18 +45,30 @@ struct backcmd { /* result of evalbackcmd */
struct job *jp; /* job structure for command */
};
#ifdef __STDC__
int evalcmd(int, char **);
void evalstring(char *);
union node; /* BLETCH for ansi C */
void evaltree(union node *, int);
void evalbackcmd(union node *, struct backcmd *);
#else
void evalstring();
void evaltree();
void evalbackcmd();
#endif
int bltincmd(int, char **);
int breakcmd(int, char **);
int returncmd(int, char **);
int falsecmd(int, char **);
int truecmd(int, char **);
int execcmd(int, char **);
int commandcmd(int, char **);
/* in_function returns nonzero if we are currently evaluating a function */
#define in_function() funcnest
extern int funcnest;
extern int evalskip;
/* reasons for skipping commands (see comment on breakcmd routine) */
#define SKIPBREAK 1
#define SKIPCONT 2
#define SKIPFUNC 3
#define SKIPFILE 4
/*
* $PchId: eval.h,v 1.3 2006/03/30 15:39:25 philip Exp $
*/

View file

@ -1,6 +1,6 @@
/*-
* Copyright (c) 1991 The Regents of the University of California.
* All rights reserved.
* Copyright (c) 1991, 1993
* The Regents of the University of California. All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* Kenneth Almquist.
@ -13,10 +13,6 @@
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
@ -35,8 +31,21 @@
*/
#ifndef lint
static char sccsid[] = "@(#)exec.c 5.2 (Berkeley) 3/13/91";
#if 0
static char sccsid[] = "@(#)exec.c 8.4 (Berkeley) 6/8/95";
#endif
#endif /* not lint */
/*
#include <sys/cdefs.h>
__FBSDID("$FreeBSD: src/bin/sh/exec.c,v 1.24.2.1 2004/09/30 04:41:55 des Exp $");
*/
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <stdlib.h>
/*
* When commands are first encountered, they are entered in a hash table.
@ -64,11 +73,9 @@ static char sccsid[] = "@(#)exec.c 5.2 (Berkeley) 3/13/91";
#include "error.h"
#include "init.h"
#include "mystring.h"
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>
#include <limits.h>
#include "show.h"
#include "jobs.h"
#include "alias.h"
#define CMDTABLESIZE 31 /* should be prime */
@ -87,23 +94,14 @@ struct tblentry {
STATIC struct tblentry *cmdtable[CMDTABLESIZE];
STATIC int builtinloc = -1; /* index in path of %builtin, or -1 */
int exerrno = 0; /* Last exec error */
#ifdef __STDC__
STATIC void tryexec(char *, char **, char **);
STATIC void execinterp(char **, char **);
STATIC void printentry(struct tblentry *);
STATIC void clearcmdentry(int);
STATIC void printentry(struct tblentry *, int);
STATIC struct tblentry *cmdlookup(char *, int);
STATIC void delete_cmd_entry(void);
#else
STATIC void tryexec();
STATIC void execinterp();
STATIC void printentry();
STATIC void clearcmdentry();
STATIC struct tblentry *cmdlookup();
STATIC void delete_cmd_entry();
#endif
STATIC void addcmdentry(char *, struct cmdentry *);
@ -113,10 +111,8 @@ STATIC void delete_cmd_entry();
*/
void
shellexec(argv, envp, path, index)
char **argv, **envp;
char *path;
{
shellexec(char **argv, char **envp, char *path, int index)
{
char *cmdname;
int e;
@ -134,40 +130,37 @@ shellexec(argv, envp, path, index)
stunalloc(cmdname);
}
}
error2(argv[0], errmsg(e, E_EXEC));
/* Map to POSIX errors */
switch (e) {
case EACCES:
exerrno = 126;
break;
case ENOENT:
exerrno = 127;
break;
default:
exerrno = 2;
break;
}
if (e == ENOENT || e == ENOTDIR)
exerror(EXEXEC, "%s: not found", argv[0]);
exerror(EXEXEC, "%s: %s", argv[0], strerror(e));
}
STATIC void
tryexec(cmd, argv, envp)
char *cmd;
char **argv;
char **envp;
{
tryexec(char *cmd, char **argv, char **envp)
{
int e;
char *p;
#ifdef SYSV
do {
execve(cmd, argv, envp);
} while (errno == EINTR);
#else
execve(cmd, argv, envp);
#endif
#if HASHBANG
#if !__minix_vmd
e = errno;
if (e == ENOEXEC) {
initshellproc();
setinputfile(cmd, 0);
commandname = arg0 = savestr(argv[0]);
#ifndef BSD
pgetc(); pungetc(); /* fill up input buffer */
p = parsenextc;
if (parsenleft > 2 && p[0] == '#' && p[1] == '!') {
argv[0] = cmd;
execinterp(argv, envp);
}
#endif
setparam(argv + 1);
exraise(EXSHELLPROC);
/*NOTREACHED*/
@ -176,88 +169,6 @@ tryexec(cmd, argv, envp)
#endif
}
#if !defined(BSD) && HASHBANG
/*
* Execute an interpreter introduced by "#!", for systems where this
* feature has not been built into the kernel. If the interpreter is
* the shell, return (effectively ignoring the "#!"). If the execution
* of the interpreter fails, exit.
*
* This code peeks inside the input buffer in order to avoid actually
* reading any input. It would benefit from a rewrite.
*/
#define NEWARGS 5
STATIC void
execinterp(argv, envp)
char **argv, **envp;
{
int n;
char *inp;
char *outp;
char c;
char *p;
char **ap;
char *newargs[NEWARGS];
int i;
char **ap2;
char **new;
n = parsenleft - 2;
inp = parsenextc + 2;
ap = newargs;
for (;;) {
while (--n >= 0 && (*inp == ' ' || *inp == '\t'))
inp++;
if (n < 0)
goto bad;
if ((c = *inp++) == '\n')
break;
if (ap == &newargs[NEWARGS])
bad: error("Bad #! line");
STARTSTACKSTR(outp);
do {
STPUTC(c, outp);
} while (--n >= 0 && (c = *inp++) != ' ' && c != '\t' && c != '\n');
STPUTC('\0', outp);
n++, inp--;
*ap++ = grabstackstr(outp);
}
#if !__minix
if (ap == newargs + 1) { /* if no args, maybe no exec is needed */
p = newargs[0];
for (;;) {
if (equal(p, "sh") || equal(p, "ash")) {
return;
}
while (*p != '/') {
if (*p == '\0')
goto break2;
p++;
}
p++;
}
break2:;
}
#endif
i = (char *)ap - (char *)newargs; /* size in bytes */
if (i == 0)
error("Bad #! line");
for (ap2 = argv ; *ap2++ != NULL ; );
new = ckmalloc(i + ((char *)ap2 - (char *)argv));
ap = newargs, ap2 = new;
while ((i -= sizeof (char **)) >= 0)
*ap2++ = *ap++;
ap = argv;
while (*ap2++ = *ap++);
shellexec(new, envp, pathval(), 0);
}
#endif
/*
* Do a path search. The variable path (passed by reference) should be
* set to the start of the path before the first call; padvance will update
@ -271,11 +182,9 @@ break2:;
char *pathopt;
char *
padvance(path, name)
char **path;
char *name;
{
register char *p, *q;
padvance(char **path, char *name)
{
char *p, *q;
char *start;
int len;
@ -288,7 +197,7 @@ padvance(path, name)
growstackblock();
q = stackblock();
if (p != start) {
bcopy(start, q, p - start);
memcpy(q, start, p - start);
q += p - start;
*q++ = '/';
}
@ -310,7 +219,9 @@ padvance(path, name)
/*** Command hashing code ***/
hashcmd(argc, argv) char **argv; {
int
hashcmd(int argc __unused, char **argv __unused)
{
struct tblentry **pp;
struct tblentry *cmdp;
int c;
@ -318,14 +229,6 @@ hashcmd(argc, argv) char **argv; {
struct cmdentry entry;
char *name;
if (argc <= 1) {
for (pp = cmdtable ; pp < &cmdtable[CMDTABLESIZE] ; pp++) {
for (cmdp = *pp ; cmdp ; cmdp = cmdp->next) {
printentry(cmdp);
}
}
return 0;
}
verbose = 0;
while ((c = nextopt("rv")) != '\0') {
if (c == 'r') {
@ -334,16 +237,28 @@ hashcmd(argc, argv) char **argv; {
verbose++;
}
}
if (*argptr == NULL) {
for (pp = cmdtable ; pp < &cmdtable[CMDTABLESIZE] ; pp++) {
for (cmdp = *pp ; cmdp ; cmdp = cmdp->next) {
if (cmdp->cmdtype == CMDNORMAL)
printentry(cmdp, verbose);
}
}
return 0;
}
while ((name = *argptr) != NULL) {
if ((cmdp = cmdlookup(name, 0)) != NULL
&& (cmdp->cmdtype == CMDNORMAL
|| cmdp->cmdtype == CMDBUILTIN && builtinloc >= 0))
|| (cmdp->cmdtype == CMDBUILTIN && builtinloc >= 0)))
delete_cmd_entry();
find_command(name, &entry, 1);
find_command(name, &entry, 1, pathval());
if (verbose) {
if (entry.cmdtype != CMDUNKNOWN) { /* if no error msg */
cmdp = cmdlookup(name, 0);
printentry(cmdp);
if (cmdp != NULL)
printentry(cmdp, verbose);
else
outfmt(&errout, "%s: not found\n", name);
}
flushall();
}
@ -354,9 +269,8 @@ hashcmd(argc, argv) char **argv; {
STATIC void
printentry(cmdp)
struct tblentry *cmdp;
{
printentry(struct tblentry *cmdp, int verbose)
{
int index;
char *path;
char *name;
@ -373,6 +287,14 @@ printentry(cmdp)
out1fmt("builtin %s", cmdp->cmdname);
} else if (cmdp->cmdtype == CMDFUNCTION) {
out1fmt("function %s", cmdp->cmdname);
if (verbose) {
INTOFF;
name = commandtext(cmdp->param.func);
out1c(' ');
out1str(name);
ckfree(name);
INTON;
}
#if DEBUG
} else {
error("internal error: cmdtype %d", cmdp->cmdtype);
@ -391,14 +313,11 @@ printentry(cmdp)
*/
void
find_command(name, entry, printerr)
char *name;
struct cmdentry *entry;
{
find_command(char *name, struct cmdentry *entry, int printerr, char *path)
{
struct tblentry *cmdp;
int index;
int prev;
char *path;
char *fullname;
struct stat statb;
int e;
@ -434,7 +353,6 @@ find_command(name, entry, printerr)
prev = cmdp->param.index;
}
path = pathval();
e = ENOENT;
index = -1;
loop:
@ -464,17 +382,13 @@ loop:
TRACE(("searchexec \"%s\": no change\n", name));
goto success;
}
while (stat(fullname, &statb) < 0) {
#ifdef SYSV
if (errno == EINTR)
continue;
#endif
if (stat(fullname, &statb) < 0) {
if (errno != ENOENT && errno != ENOTDIR)
e = errno;
goto loop;
}
e = EACCES; /* if we fail, this will be the error */
if ((statb.st_mode & S_IFMT) != S_IFREG)
if (!S_ISREG(statb.st_mode))
goto loop;
if (pathopt) { /* this is a %func directory */
stalloc(strlen(fullname) + 1);
@ -484,6 +398,7 @@ loop:
stunalloc(fullname);
goto success;
}
#ifdef notdef
if (statb.st_uid == geteuid()) {
if ((statb.st_mode & 0100) == 0)
goto loop;
@ -491,23 +406,10 @@ loop:
if ((statb.st_mode & 010) == 0)
goto loop;
} else {
#if __minix_vmd || defined(BSD)
gid_t group_list[NGROUPS_MAX];
int ngroups, i;
ngroups = getgroups(NGROUPS_MAX, group_list);
for (i = 0; i < ngroups; i++) {
if (statb.st_gid == group_list[i]) break;
}
if (i < ngroups) {
if ((statb.st_mode & 010) == 0)
goto loop;
} else
#endif
if ((statb.st_mode & 01) == 0)
goto loop;
}
#endif
TRACE(("searchexec \"%s\" returns \"%s\"\n", name, fullname));
INTOFF;
cmdp = cmdlookup(name, 1);
@ -520,8 +422,12 @@ loop:
/* We failed. If there was an entry for this command, delete it */
if (cmdp)
delete_cmd_entry();
if (printerr)
outfmt(out2, "%s: %s\n", name, errmsg(e, E_EXEC));
if (printerr) {
if (e == ENOENT || e == ENOTDIR)
outfmt(out2, "%s: not found\n", name);
else
outfmt(out2, "%s: %s\n", name, strerror(e));
}
entry->cmdtype = CMDUNKNOWN;
return;
@ -538,10 +444,9 @@ success:
*/
int
find_builtin(name)
char *name;
{
const register struct builtincmd *bp;
find_builtin(char *name)
{
const struct builtincmd *bp;
for (bp = builtincmd ; bp->name ; bp++) {
if (*bp->name == *name && equal(bp->name, name))
@ -558,14 +463,15 @@ find_builtin(name)
*/
void
hashcd() {
hashcd(void)
{
struct tblentry **pp;
struct tblentry *cmdp;
for (pp = cmdtable ; pp < &cmdtable[CMDTABLESIZE] ; pp++) {
for (cmdp = *pp ; cmdp ; cmdp = cmdp->next) {
if (cmdp->cmdtype == CMDNORMAL
|| cmdp->cmdtype == CMDBUILTIN && builtinloc >= 0)
|| (cmdp->cmdtype == CMDBUILTIN && builtinloc >= 0))
cmdp->rehash = 1;
}
}
@ -580,10 +486,9 @@ hashcd() {
*/
void
changepath(newval)
char *newval;
{
char *old, *new;
changepath(const char *newval)
{
const char *old, *new;
int index;
int firstchange;
int bltin;
@ -596,8 +501,8 @@ changepath(newval)
for (;;) {
if (*old != *new) {
firstchange = index;
if (*old == '\0' && *new == ':'
|| *old == ':' && *new == '\0')
if ((*old == '\0' && *new == ':')
|| (*old == ':' && *new == '\0'))
firstchange++;
old = new; /* ignore subsequent differences */
}
@ -624,8 +529,9 @@ changepath(newval)
* PATH which has changed.
*/
STATIC void
clearcmdentry(firstchange) {
void
clearcmdentry(int firstchange)
{
struct tblentry **tblp;
struct tblentry **pp;
struct tblentry *cmdp;
@ -634,8 +540,10 @@ clearcmdentry(firstchange) {
for (tblp = cmdtable ; tblp < &cmdtable[CMDTABLESIZE] ; tblp++) {
pp = tblp;
while ((cmdp = *pp) != NULL) {
if (cmdp->cmdtype == CMDNORMAL && cmdp->param.index >= firstchange
|| cmdp->cmdtype == CMDBUILTIN && builtinloc >= firstchange) {
if ((cmdp->cmdtype == CMDNORMAL &&
cmdp->param.index >= firstchange)
|| (cmdp->cmdtype == CMDBUILTIN &&
builtinloc >= firstchange)) {
*pp = cmdp->next;
ckfree(cmdp);
} else {
@ -652,15 +560,15 @@ clearcmdentry(firstchange) {
*/
#ifdef mkinit
MKINIT void deletefuncs();
INCLUDE "exec.h"
SHELLPROC {
deletefuncs();
}
#endif
void
deletefuncs() {
deletefuncs(void)
{
struct tblentry **tblp;
struct tblentry **pp;
struct tblentry *cmdp;
@ -691,15 +599,14 @@ deletefuncs() {
* entry.
*/
struct tblentry **lastcmdentry;
STATIC struct tblentry **lastcmdentry;
STATIC struct tblentry *
cmdlookup(name, add)
char *name;
{
cmdlookup(char *name, int add)
{
int hashval;
register char *p;
char *p;
struct tblentry *cmdp;
struct tblentry **pp;
@ -728,13 +635,13 @@ cmdlookup(name, add)
return cmdp;
}
/*
* Delete the command entry returned on the last lookup.
*/
STATIC void
delete_cmd_entry() {
delete_cmd_entry(void)
{
struct tblentry *cmdp;
INTOFF;
@ -746,35 +653,14 @@ delete_cmd_entry() {
#ifdef notdef
void
getcmdentry(name, entry)
char *name;
struct cmdentry *entry;
{
struct tblentry *cmdp = cmdlookup(name, 0);
if (cmdp) {
entry->u = cmdp->param;
entry->cmdtype = cmdp->cmdtype;
} else {
entry->cmdtype = CMDUNKNOWN;
entry->u.index = 0;
}
}
#endif
/*
* Add a new command entry, replacing any existing command entry for
* the same name.
*/
void
addcmdentry(name, entry)
char *name;
struct cmdentry *entry;
{
static void
addcmdentry(char *name, struct cmdentry *entry)
{
struct tblentry *cmdp;
INTOFF;
@ -793,10 +679,8 @@ addcmdentry(name, entry)
*/
void
defun(name, func)
char *name;
union node *func;
{
defun(char *name, union node *func)
{
struct cmdentry entry;
INTOFF;
@ -811,14 +695,98 @@ defun(name, func)
* Delete a function if it exists.
*/
void
unsetfunc(name)
char *name;
{
int
unsetfunc(char *name)
{
struct tblentry *cmdp;
if ((cmdp = cmdlookup(name, 0)) != NULL && cmdp->cmdtype == CMDFUNCTION) {
freefunc(cmdp->param.func);
delete_cmd_entry();
return (0);
}
return (0);
}
/*
* Locate and print what a word is...
*/
int
typecmd(int argc, char **argv)
{
struct cmdentry entry;
struct tblentry *cmdp;
char **pp;
struct alias *ap;
int i;
int error = 0;
extern char *const parsekwd[];
for (i = 1; i < argc; i++) {
out1str(argv[i]);
/* First look at the keywords */
for (pp = (char **)parsekwd; *pp; pp++)
if (**pp == *argv[i] && equal(*pp, argv[i]))
break;
if (*pp) {
out1str(" is a shell keyword\n");
continue;
}
/* Then look at the aliases */
if ((ap = lookupalias(argv[i], 1)) != NULL) {
out1fmt(" is an alias for %s\n", ap->val);
continue;
}
/* Then check if it is a tracked alias */
if ((cmdp = cmdlookup(argv[i], 0)) != NULL) {
entry.cmdtype = cmdp->cmdtype;
entry.u = cmdp->param;
}
else {
/* Finally use brute force */
find_command(argv[i], &entry, 0, pathval());
}
switch (entry.cmdtype) {
case CMDNORMAL: {
if (strchr(argv[i], '/') == NULL) {
char *path = pathval(), *name;
int j = entry.u.index;
do {
name = padvance(&path, argv[i]);
stunalloc(name);
} while (--j >= 0);
out1fmt(" is%s %s\n",
cmdp ? " a tracked alias for" : "", name);
} else {
if (access(argv[i], X_OK) == 0)
out1fmt(" is %s\n", argv[i]);
else
out1fmt(": %s\n", strerror(errno));
}
break;
}
case CMDFUNCTION:
out1str(" is a shell function\n");
break;
case CMDBUILTIN:
out1str(" is a shell builtin\n");
break;
default:
out1str(": not found\n");
error |= 127;
break;
}
}
return error;
}
/*
* $PchId: exec.c,v 1.6 2006/04/10 14:47:03 philip Exp $
*/

View file

@ -1,6 +1,6 @@
/*-
* Copyright (c) 1991 The Regents of the University of California.
* All rights reserved.
* Copyright (c) 1991, 1993
* The Regents of the University of California. All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* Kenneth Almquist.
@ -13,10 +13,6 @@
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
@ -33,7 +29,8 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* @(#)exec.h 5.1 (Berkeley) 3/7/91
* @(#)exec.h 8.3 (Berkeley) 6/8/95
* $FreeBSD: src/bin/sh/exec.h,v 1.12 2004/04/06 20:06:51 markm Exp $
*/
/* values of cmdtype */
@ -53,23 +50,21 @@ struct cmdentry {
extern char *pathopt; /* set by padvance */
extern int exerrno; /* last exec error */
#ifdef __STDC__
void shellexec(char **, char **, char *, int);
char *padvance(char **, char *);
void find_command(char *, struct cmdentry *, int);
int hashcmd(int, char **);
void find_command(char *, struct cmdentry *, int, char *);
int find_builtin(char *);
void hashcd(void);
void changepath(char *);
void changepath(const char *);
void deletefuncs(void);
void defun(char *, union node *);
void unsetfunc(char *);
#else
void shellexec();
char *padvance();
void find_command();
int find_builtin();
void hashcd();
void changepath();
void defun();
void unsetfunc();
#endif
int unsetfunc(char *);
int typecmd(int, char **);
void clearcmdentry(int);
/*
* $PchId: exec.h,v 1.5 2006/04/10 14:47:34 philip Exp $
*/

File diff suppressed because it is too large Load diff

View file

@ -1,6 +1,6 @@
/*-
* Copyright (c) 1991 The Regents of the University of California.
* All rights reserved.
* Copyright (c) 1991, 1993
* The Regents of the University of California. All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* Kenneth Almquist.
@ -13,10 +13,6 @@
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
@ -33,7 +29,8 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* @(#)expand.h 5.1 (Berkeley) 3/7/91
* @(#)expand.h 8.2 (Berkeley) 5/4/95
* $FreeBSD: src/bin/sh/expand.h,v 1.12 2004/04/06 20:06:51 markm Exp $
*/
struct strlist {
@ -47,17 +44,24 @@ struct arglist {
struct strlist **lastp;
};
#ifdef __STDC__
/*
* expandarg() flags
*/
#define EXP_FULL 0x1 /* perform word splitting & file globbing */
#define EXP_TILDE 0x2 /* do normal tilde expansion */
#define EXP_VARTILDE 0x4 /* expand tildes in an assignment */
#define EXP_REDIR 0x8 /* file glob for a redirection (1 match only) */
#define EXP_CASE 0x10 /* keeps quotes around for CASE pattern */
union node;
void expandarg(union node *, struct arglist *, int);
void expandhere(union node *, int);
int patmatch(char *, char *);
void expandarg(union node *, struct arglist *, int);
int patmatch(char *, char *, int);
void rmescapes(char *);
int casematch(union node *, char *);
#else
void expandarg();
void expandhere();
int patmatch();
void rmescapes();
int casematch();
#endif
int wordexpcmd(int, char **);
/*
* $PchId: expand.h,v 1.4 2006/03/30 14:50:52 philip Exp $
*/

View file

@ -1,5 +1,5 @@
# Copyright (c) 1991 The Regents of the University of California.
# All rights reserved.
# Copyright (c) 1991, 1993
# The Regents of the University of California. All rights reserved.
#
# This code is derived from software contributed to Berkeley by
# Kenneth Almquist.
@ -12,10 +12,6 @@
# 2. Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
# 3. All advertising materials mentioning features or use of this software
# must display the following acknowledgement:
# This product includes software developed by the University of
# California, Berkeley and its contributors.
# 4. Neither the name of the University nor the names of its contributors
# may be used to endorse or promote products derived from this software
# without specific prior written permission.
@ -32,7 +28,8 @@
# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
# SUCH DAMAGE.
#
# @(#)cmv 5.1 (Berkeley) 3/7/91
# @(#)cmv 8.2 (Berkeley) 5/4/95
# $FreeBSD: src/bin/sh/funcs/cmv,v 1.7 2004/04/06 20:06:53 markm Exp $
# Conditional move--don't replace an existing file.
@ -47,3 +44,6 @@ cmv() {
fi
/bin/mv "$1" "$2"
}
#
# $PchId: cmv,v 1.2 2006/03/29 10:43:18 philip Exp $

View file

@ -1,5 +1,5 @@
# Copyright (c) 1991 The Regents of the University of California.
# All rights reserved.
# Copyright (c) 1991, 1993
# The Regents of the University of California. All rights reserved.
#
# This code is derived from software contributed to Berkeley by
# Kenneth Almquist.
@ -12,10 +12,6 @@
# 2. Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
# 3. All advertising materials mentioning features or use of this software
# must display the following acknowledgement:
# This product includes software developed by the University of
# California, Berkeley and its contributors.
# 4. Neither the name of the University nor the names of its contributors
# may be used to endorse or promote products derived from this software
# without specific prior written permission.
@ -32,7 +28,8 @@
# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
# SUCH DAMAGE.
#
# @(#)dirs 5.1 (Berkeley) 3/7/91
# @(#)dirs 8.2 (Berkeley) 5/4/95
# $FreeBSD: src/bin/sh/funcs/dirs,v 1.7 2004/04/06 20:06:53 markm Exp $
# pushd, popd, and dirs --- written by Chris Bertin
# Pixel Computer Inc. ...!wjh12!pixel!pixutl!chris
@ -71,3 +68,6 @@ dirs () {
echo "`pwd` $DSTACK"
return 0
}
#
# $PchId: dirs,v 1.2 2006/03/29 10:43:18 philip Exp $

View file

@ -1,5 +1,5 @@
# Copyright (c) 1991 The Regents of the University of California.
# All rights reserved.
# Copyright (c) 1991, 1993
# The Regents of the University of California. All rights reserved.
#
# This code is derived from software contributed to Berkeley by
# Kenneth Almquist.
@ -12,10 +12,6 @@
# 2. Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
# 3. All advertising materials mentioning features or use of this software
# must display the following acknowledgement:
# This product includes software developed by the University of
# California, Berkeley and its contributors.
# 4. Neither the name of the University nor the names of its contributors
# may be used to endorse or promote products derived from this software
# without specific prior written permission.
@ -32,7 +28,8 @@
# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
# SUCH DAMAGE.
#
# @(#)kill 5.1 (Berkeley) 3/7/91
# @(#)kill 8.2 (Berkeley) 5/4/95
# $FreeBSD: src/bin/sh/funcs/kill,v 1.7 2004/04/06 20:06:53 markm Exp $
# Convert job names to process ids and then run /bin/kill.
@ -47,3 +44,6 @@ kill() {
done
/bin/kill $args
}
#
# $PchId: kill,v 1.2 2006/03/29 10:43:18 philip Exp $

View file

@ -1,5 +1,5 @@
# Copyright (c) 1991 The Regents of the University of California.
# All rights reserved.
# Copyright (c) 1991, 1993
# The Regents of the University of California. All rights reserved.
#
# This code is derived from software contributed to Berkeley by
# Kenneth Almquist.
@ -12,10 +12,6 @@
# 2. Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
# 3. All advertising materials mentioning features or use of this software
# must display the following acknowledgement:
# This product includes software developed by the University of
# California, Berkeley and its contributors.
# 4. Neither the name of the University nor the names of its contributors
# may be used to endorse or promote products derived from this software
# without specific prior written permission.
@ -32,7 +28,11 @@
# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
# SUCH DAMAGE.
#
# @(#)login 5.1 (Berkeley) 3/7/91
# @(#)login 8.2 (Berkeley) 5/4/95
# $FreeBSD: src/bin/sh/funcs/login,v 1.7 2004/04/06 20:06:53 markm Exp $
# replaces the login builtin in the BSD shell
login () exec login "$@"
#
# $PchId: login,v 1.2 2006/03/29 10:43:18 philip Exp $

View file

@ -1,5 +1,5 @@
# Copyright (c) 1991 The Regents of the University of California.
# All rights reserved.
# Copyright (c) 1991, 1993
# The Regents of the University of California. All rights reserved.
#
# This code is derived from software contributed to Berkeley by
# Kenneth Almquist.
@ -12,10 +12,6 @@
# 2. Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
# 3. All advertising materials mentioning features or use of this software
# must display the following acknowledgement:
# This product includes software developed by the University of
# California, Berkeley and its contributors.
# 4. Neither the name of the University nor the names of its contributors
# may be used to endorse or promote products derived from this software
# without specific prior written permission.
@ -32,6 +28,10 @@
# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
# SUCH DAMAGE.
#
# @(#)newgrp 5.1 (Berkeley) 3/7/91
# @(#)newgrp 8.2 (Berkeley) 5/4/95
# $FreeBSD: src/bin/sh/funcs/newgrp,v 1.7 2004/04/06 20:06:53 markm Exp $
newgrp() exec newgrp "$@"
#
# $PchId: newgrp,v 1.2 2006/03/29 10:43:18 philip Exp $

View file

@ -1,5 +1,5 @@
# Copyright (c) 1991 The Regents of the University of California.
# All rights reserved.
# Copyright (c) 1991, 1993
# The Regents of the University of California. All rights reserved.
#
# This code is derived from software contributed to Berkeley by
# Kenneth Almquist.
@ -12,10 +12,6 @@
# 2. Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
# 3. All advertising materials mentioning features or use of this software
# must display the following acknowledgement:
# This product includes software developed by the University of
# California, Berkeley and its contributors.
# 4. Neither the name of the University nor the names of its contributors
# may be used to endorse or promote products derived from this software
# without specific prior written permission.
@ -32,7 +28,8 @@
# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
# SUCH DAMAGE.
#
# @(#)popd 5.1 (Berkeley) 3/7/91
# @(#)popd 8.2 (Berkeley) 5/4/95
# $FreeBSD: src/bin/sh/funcs/popd,v 1.7 2004/04/06 20:06:53 markm Exp $
# pushd, popd, and dirs --- written by Chris Bertin
# Pixel Computer Inc. ...!wjh12!pixel!pixutl!chris
@ -71,3 +68,6 @@ dirs () {
echo "`pwd` $DSTACK"
return 0
}
#
# $PchId: popd,v 1.2 2006/03/29 10:43:18 philip Exp $

View file

@ -1,5 +1,5 @@
# Copyright (c) 1991 The Regents of the University of California.
# All rights reserved.
# Copyright (c) 1991, 1993
# The Regents of the University of California. All rights reserved.
#
# This code is derived from software contributed to Berkeley by
# Kenneth Almquist.
@ -12,10 +12,6 @@
# 2. Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
# 3. All advertising materials mentioning features or use of this software
# must display the following acknowledgement:
# This product includes software developed by the University of
# California, Berkeley and its contributors.
# 4. Neither the name of the University nor the names of its contributors
# may be used to endorse or promote products derived from this software
# without specific prior written permission.
@ -32,7 +28,8 @@
# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
# SUCH DAMAGE.
#
# @(#)pushd 5.1 (Berkeley) 3/7/91
# @(#)pushd 8.2 (Berkeley) 5/4/95
# $FreeBSD: src/bin/sh/funcs/pushd,v 1.7 2004/04/06 20:06:53 markm Exp $
# pushd, popd, and dirs --- written by Chris Bertin
# Pixel Computer Inc. ...!wjh12!pixel!pixutl!chris
@ -71,3 +68,6 @@ dirs () {
echo "`pwd` $DSTACK"
return 0
}
#
# $PchId: pushd,v 1.2 2006/03/29 10:43:18 philip Exp $

View file

@ -1,5 +1,5 @@
# Copyright (c) 1991 The Regents of the University of California.
# All rights reserved.
# Copyright (c) 1991, 1993
# The Regents of the University of California. All rights reserved.
#
# This code is derived from software contributed to Berkeley by
# Kenneth Almquist.
@ -12,10 +12,6 @@
# 2. Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
# 3. All advertising materials mentioning features or use of this software
# must display the following acknowledgement:
# This product includes software developed by the University of
# California, Berkeley and its contributors.
# 4. Neither the name of the University nor the names of its contributors
# may be used to endorse or promote products derived from this software
# without specific prior written permission.
@ -32,10 +28,14 @@
# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
# SUCH DAMAGE.
#
# @(#)suspend 5.1 (Berkeley) 3/7/91
# @(#)suspend 8.2 (Berkeley) 5/4/95
# $FreeBSD: src/bin/sh/funcs/suspend,v 1.7 2004/04/06 20:06:53 markm Exp $
suspend() {
local -
set +j
kill -TSTP 0
}
#
# $PchId: suspend,v 1.2 2006/03/29 10:43:18 philip Exp $

533
commands/ash/histedit.c Normal file
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.
* All rights reserved.
* Copyright (c) 1991, 1993
* The Regents of the University of California. All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* Kenneth Almquist.
@ -13,10 +13,6 @@
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
@ -33,15 +29,14 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* @(#)init.h 5.1 (Berkeley) 3/7/91
* @(#)init.h 8.2 (Berkeley) 5/4/95
* $FreeBSD: src/bin/sh/init.h,v 1.8 2004/04/06 20:06:51 markm Exp $
*/
#ifdef __STDC__
void init(void);
void reset(void);
void initshellproc(void);
#else
void init();
void reset();
void initshellproc();
#endif
/*
* $PchId: init.h,v 1.3 2006/03/30 14:31:06 philip Exp $
*/

View file

@ -1,6 +1,6 @@
/*-
* Copyright (c) 1991 The Regents of the University of California.
* All rights reserved.
* Copyright (c) 1991, 1993
* The Regents of the University of California. All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* Kenneth Almquist.
@ -13,10 +13,6 @@
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
@ -35,26 +31,61 @@
*/
#ifndef lint
static char sccsid[] = "@(#)input.c 5.4 (Berkeley) 7/1/91";
#if 0
static char sccsid[] = "@(#)input.c 8.3 (Berkeley) 6/9/95";
#endif
#endif /* not lint */
/*
#include <sys/cdefs.h>
__FBSDID("$FreeBSD: src/bin/sh/input.c,v 1.22 2004/04/06 20:06:51 markm Exp $");
*/
#include <sys/types.h>
#include <stdio.h> /* defines BUFSIZ */
#include <fcntl.h>
#include <errno.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
/*
* This file implements the input routines used by the parser.
*/
#include <sys/types.h>
#include <stdio.h> /* defines BUFSIZ */
#include "shell.h"
#include <fcntl.h>
#include <errno.h>
#include "redir.h"
#include "syntax.h"
#include "input.h"
#include "output.h"
#include "options.h"
#include "memalloc.h"
#include "error.h"
#include "alias.h"
#include "parser.h"
#ifdef EDITLINE
#ifdef __minix_vmd
#include <readline/readline.h>
#else
/* What about other systems? */
#endif
#else
#include "myhistedit.h"
#endif
#include "redir.h"
#include "trap.h"
static void popstring(void);
#define EOF_NLEFT -99 /* value of parsenleft when EOF pushed back */
MKINIT
struct strpush {
struct strpush *prev; /* preceding string on stack */
char *prevstring;
int prevnleft;
int prevlleft;
struct alias *ap; /* if push was associated with an alias */
};
/*
* The parsefile structure pointed to by the global variable parsefile
@ -63,36 +94,34 @@ static char sccsid[] = "@(#)input.c 5.4 (Berkeley) 7/1/91";
MKINIT
struct parsefile {
struct parsefile *prev; /* preceding file on stack */
int linno; /* current line */
int fd; /* file descriptor (or -1 if string) */
int nleft; /* number of chars left in buffer */
int nleft; /* number of chars left in this line */
int lleft; /* number of lines left in this buffer */
char *nextc; /* next char in buffer */
struct parsefile *prev; /* preceding file on stack */
char *buf; /* input buffer */
struct strpush *strpush; /* for pushing strings at this level */
struct strpush basestrpush; /* so pushing one is fast */
};
int plinno = 1; /* input line number */
MKINIT int parsenleft; /* copy of parsefile->nleft */
MKINIT int parselleft; /* copy of parsefile->lleft */
char *parsenextc; /* copy of parsefile->nextc */
MKINIT struct parsefile basepf; /* top level input file */
char basebuf[BUFSIZ]; /* buffer for top level input file */
struct parsefile *parsefile = &basepf; /* current input file */
char *pushedstring; /* copy of parsenextc when text pushed back */
int pushednleft; /* copy of parsenleft when text pushed back */
STATIC struct parsefile *parsefile = &basepf; /* current input file */
int init_editline = 0; /* editline library initialized? */
int whichprompt; /* -1 == PSE, 1 == PS1, 2 == PS2 */
#if READLINE
char *readline __P((const char *prompt));
char *r_use_prompt = NULL; /* the prompt to use with readline */
#ifndef EDITLINE
EditLine *el; /* cookie for editline package */
#endif
#ifdef __STDC__
STATIC void pushfile(void);
#else
STATIC void pushfile();
#endif
static int preadfd(void);
#ifdef mkinit
INCLUDE "input.h"
@ -106,7 +135,7 @@ INIT {
RESET {
if (exception != EXSHELLPROC)
parsenleft = 0; /* clear input buffer */
parselleft = parsenleft = 0; /* clear input buffer */
popallfiles();
}
@ -121,10 +150,9 @@ SHELLPROC {
*/
char *
pfgets(line, len)
char *line;
{
register char *p = line;
pfgets(char *line, int len)
{
char *p = line;
int nleft = len;
int c;
@ -151,64 +179,74 @@ pfgets(line, len)
*/
int
pgetc() {
pgetc(void)
{
return pgetc_macro();
}
/*
* Refill the input buffer and return the next input character:
*
* 1) If a string was pushed back on the input, switch back to the regular
* buffer.
* 2) If an EOF was pushed back (parsenleft == EOF_NLEFT) or we are reading
* from a string so we can't refill the buffer, return EOF.
* 3) Call read to read in the characters.
* 4) Delete all nul characters from the buffer.
*/
static int
preadfd(void)
{
int nr;
parsenextc = parsefile->buf;
int
preadbuffer() {
register char *p, *q;
register int i;
if (pushedstring) {
parsenextc = pushedstring;
pushedstring = NULL;
parsenleft = pushednleft;
if (--parsenleft >= 0)
return *parsenextc++;
#if !defined(NO_HISTORY) && !defined(EDITLINE)
if (el != NULL && gotwinch) {
gotwinch = 0;
el_resize(el);
}
if (parsenleft == EOF_NLEFT || parsefile->buf == NULL)
return PEOF;
flushout(&output);
flushout(&errout);
#if READLINE
/* Use the readline() call if a prompt is to be printed (interactive). */
if (r_use_prompt != NULL) {
char *prompt;
char *line;
p = parsenextc = parsefile->buf;
prompt = r_use_prompt;
r_use_prompt = NULL;
if ((line = readline(prompt)) == NULL) {
parsenleft = EOF_NLEFT;
return PEOF;
}
strcpy(p, line);
free(line);
i = strlen(p);
p[i++] = '\n';
} else {
#endif
retry:
p = parsenextc = parsefile->buf;
i = read(parsefile->fd, p, BUFSIZ);
if (i <= 0) {
if (i < 0) {
#ifndef NO_HISTORY
#ifdef EDITLINE
if (parsefile->fd == 0) {
static const char *rl_cp= NULL;
static size_t rl_off= 0;
if (!rl_cp)
{
rl_cp = readline(getprompt(NULL));
if (rl_cp == NULL)
nr = 0;
}
if (rl_cp)
{
nr= strlen(rl_cp+rl_off);
if (nr >= BUFSIZ-1)
{
nr= BUFSIZ-1;
(void) memcpy(parsenextc, rl_cp+rl_off, nr);
rl_off += nr;
}
else
{
(void) memcpy(parsenextc, rl_cp+rl_off, nr);
parsenextc[nr++]= '\n';
free(rl_cp);
rl_cp= NULL;
rl_off= 0;
}
}
} else
#else /* !EDITLINE */
if (parsefile->fd == 0 && el) {
const char *rl_cp;
rl_cp = el_gets(el, &nr);
if (rl_cp == NULL)
nr = 0;
else {
/* XXX - BUFSIZE should redesign so not necessary */
(void) strcpy(parsenextc, rl_cp);
}
} else
#endif /* !EDITLINE */
#endif
nr = read(parsefile->fd, parsenextc, BUFSIZ - 1);
if (nr <= 0) {
if (nr < 0) {
if (errno == EINTR)
goto retry;
#ifdef EWOULDBLOCK
@ -222,35 +260,106 @@ retry:
}
}
}
#endif
#endif /* EWOULDBLOCK */
}
parsenleft = EOF_NLEFT;
return PEOF;
nr = -1;
}
#if READLINE
}
#endif
parsenleft = i - 1;
/* delete nul characters */
for (;;) {
if (*p++ == '\0')
break;
if (--i <= 0)
return *parsenextc++; /* no nul characters */
}
q = p - 1;
while (--i > 0) {
if (*p != '\0')
*q++ = *p;
p++;
}
if (q == parsefile->buf)
goto retry; /* buffer contained nothing but nuls */
parsenleft = q - parsefile->buf - 1;
return *parsenextc++;
return nr;
}
/*
* Refill the input buffer and return the next input character:
*
* 1) If a string was pushed back on the input, pop it;
* 2) If an EOF was pushed back (parsenleft == EOF_NLEFT) or we are reading
* from a string so we can't refill the buffer, return EOF.
* 3) If there is more in this buffer, use it else call read to fill it.
* 4) Process input up to the next newline, deleting nul characters.
*/
int
preadbuffer(void)
{
char *p, *q;
int more;
int something;
char savec;
if (parsefile->strpush) {
popstring();
if (--parsenleft >= 0)
return (*parsenextc++);
}
if (parsenleft == EOF_NLEFT || parsefile->buf == NULL)
return PEOF;
flushout(&output);
flushout(&errout);
again:
if (parselleft <= 0) {
if ((parselleft = preadfd()) == -1) {
parselleft = parsenleft = EOF_NLEFT;
return PEOF;
}
}
q = p = parsenextc;
/* delete nul characters */
something = 0;
for (more = 1; more;) {
switch (*p) {
case '\0':
p++; /* Skip nul */
goto check;
case '\t':
case ' ':
break;
case '\n':
parsenleft = q - parsenextc;
more = 0; /* Stop processing here */
break;
default:
something = 1;
break;
}
*q++ = *p++;
check:
if (--parselleft <= 0) {
parsenleft = q - parsenextc - 1;
if (parsenleft < 0)
goto again;
*q = '\0';
more = 0;
}
}
savec = *q;
*q = '\0';
#if !defined(NO_HISTORY) && !defined(EDITLINE)
if (parsefile->fd == 0 && hist && something) {
HistEvent he;
INTOFF;
history(hist, &he, whichprompt == 1 ? H_ENTER : H_ADD,
parsenextc);
INTON;
}
#endif
if (vflag) {
out2str(parsenextc);
flushout(out2);
}
*q = savec;
return *parsenextc++;
}
/*
* Undo the last call to pgetc. Only one character may be pushed back.
@ -258,28 +367,57 @@ retry:
*/
void
pungetc() {
pungetc(void)
{
parsenleft++;
parsenextc--;
}
/*
* Push a string back onto the input. This code doesn't work if the user
* tries to push back more than one string at once.
* Push a string back onto the input at this current parsefile level.
* We handle aliases this way.
*/
void
ppushback(string, length)
char *string;
{
pushedstring = parsenextc;
pushednleft = parsenleft;
parsenextc = string;
parsenleft = length;
pushstring(char *s, int len, void *ap)
{
struct strpush *sp;
INTOFF;
/*dprintf("*** calling pushstring: %s, %d\n", s, len);*/
if (parsefile->strpush) {
sp = ckmalloc(sizeof (struct strpush));
sp->prev = parsefile->strpush;
parsefile->strpush = sp;
} else
sp = parsefile->strpush = &(parsefile->basestrpush);
sp->prevstring = parsenextc;
sp->prevnleft = parsenleft;
sp->prevlleft = parselleft;
sp->ap = (struct alias *)ap;
if (ap)
((struct alias *)ap)->flag |= ALIASINUSE;
parsenextc = s;
parsenleft = len;
INTON;
}
static void
popstring(void)
{
struct strpush *sp = parsefile->strpush;
INTOFF;
parsenextc = sp->prevstring;
parsenleft = sp->prevnleft;
parselleft = sp->prevlleft;
/*dprintf("*** calling popstring: restoring to '%s'\n", parsenextc);*/
if (sp->ap)
sp->ap->flag &= ~ALIASINUSE;
parsefile->strpush = sp->prev;
if (sp != &(parsefile->basestrpush))
ckfree(sp);
INTON;
}
/*
* Set the input to take input from a file. If push is set, push the
@ -287,17 +425,16 @@ ppushback(string, length)
*/
void
setinputfile(fname, push)
char *fname;
{
setinputfile(char *fname, int push)
{
int fd;
int fd2;
INTOFF;
if ((fd = open(fname, O_RDONLY)) < 0)
error("Can't open %s", fname);
error("Can't open %s: %s", fname, strerror(errno));
if (fd < 10) {
fd2 = copyfd(fd, 10);
fd2 = fcntl(fd, F_DUPFD, 10);
close(fd);
if (fd2 < 0)
error("Out of file descriptors");
@ -314,8 +451,9 @@ setinputfile(fname, push)
*/
void
setinputfd(fd, push) {
(void) fcntl(fd, F_SETFD, fcntl(fd, F_GETFD) | FD_CLOEXEC);
setinputfd(int fd, int push)
{
(void)fcntl(fd, F_SETFD, FD_CLOEXEC);
if (push) {
pushfile();
parsefile->buf = ckmalloc(BUFSIZ);
@ -325,7 +463,7 @@ setinputfd(fd, push) {
parsefile->fd = fd;
if (parsefile->buf == NULL)
parsefile->buf = ckmalloc(BUFSIZ);
parsenleft = 0;
parselleft = parsenleft = 0;
plinno = 1;
}
@ -335,14 +473,13 @@ setinputfd(fd, push) {
*/
void
setinputstring(string, push)
char *string;
{
setinputstring(char *string, int push)
{
INTOFF;
if (push)
pushfile();
parsenextc = string;
parsenleft = strlen(string);
parselleft = parsenleft = strlen(string);
parsefile->buf = NULL;
plinno = 1;
INTON;
@ -356,21 +493,26 @@ setinputstring(string, push)
*/
STATIC void
pushfile() {
pushfile(void)
{
struct parsefile *pf;
parsefile->nleft = parsenleft;
parsefile->lleft = parselleft;
parsefile->nextc = parsenextc;
parsefile->linno = plinno;
pf = (struct parsefile *)ckmalloc(sizeof (struct parsefile));
pf->prev = parsefile;
pf->fd = -1;
pf->strpush = NULL;
pf->basestrpush.prev = NULL;
parsefile = pf;
}
void
popfile() {
popfile(void)
{
struct parsefile *pf = parsefile;
INTOFF;
@ -378,9 +520,12 @@ popfile() {
close(pf->fd);
if (pf->buf)
ckfree(pf->buf);
while (pf->strpush)
popstring();
parsefile = pf->prev;
ckfree(pf);
parsenleft = parsefile->nleft;
parselleft = parsefile->lleft;
parsenextc = parsefile->nextc;
plinno = parsefile->linno;
INTON;
@ -392,7 +537,8 @@ popfile() {
*/
void
popallfiles() {
popallfiles(void)
{
while (parsefile != &basepf)
popfile();
}
@ -405,10 +551,15 @@ popallfiles() {
*/
void
closescript() {
closescript(void)
{
popallfiles();
if (parsefile->fd > 0) {
close(parsefile->fd);
parsefile->fd = 0;
}
}
/*
* $PchId: input.c,v 1.6 2006/05/23 12:00:32 philip Exp $
*/

View file

@ -1,6 +1,6 @@
/*-
* Copyright (c) 1991 The Regents of the University of California.
* All rights reserved.
* Copyright (c) 1991, 1993
* The Regents of the University of California. All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* Kenneth Almquist.
@ -13,10 +13,6 @@
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
@ -33,7 +29,8 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* @(#)input.h 5.1 (Berkeley) 3/7/91
* @(#)input.h 8.2 (Berkeley) 5/4/95
* $FreeBSD: src/bin/sh/input.h,v 1.9 2004/04/06 20:06:51 markm Exp $
*/
/* PEOF (the end of file marker) is defined in syntax.h */
@ -46,39 +43,22 @@
extern int plinno;
extern int parsenleft; /* number of characters left in input buffer */
extern char *parsenextc; /* next character in input buffer */
extern int init_editline; /* 0 == not setup, 1 == OK, -1 == failed */
#ifdef __STDC__
char *pfgets(char *, int);
int pgetc(void);
int preadbuffer(void);
void pungetc(void);
void ppushback(char *, int);
void pushstring(char *, int, void *);
void setinputfile(char *, int);
void setinputfd(int, int);
void setinputstring(char *, int);
void popfile(void);
void popallfiles(void);
void closescript(void);
#else
char *pfgets();
int pgetc();
int preadbuffer();
void pungetc();
void ppushback();
void setinputfile();
void setinputfd();
void setinputstring();
void popfile();
void popallfiles();
void closescript();
#endif
#define pgetc_macro() (--parsenleft >= 0? *parsenextc++ : preadbuffer())
#if READLINE
/* The variable "r_use_prompt" indicates the prompt to use with readline,
* *and* that readline may only be used if non-NULL.
/*
* $PchId: input.h,v 1.3 2006/03/30 13:49:37 philip Exp $
*/
extern char *r_use_prompt;
#endif

File diff suppressed because it is too large Load diff

View file

@ -1,6 +1,6 @@
/*-
* Copyright (c) 1991 The Regents of the University of California.
* All rights reserved.
* Copyright (c) 1991, 1993
* The Regents of the University of California. All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* Kenneth Almquist.
@ -13,10 +13,6 @@
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
@ -33,7 +29,8 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* @(#)jobs.h 5.1 (Berkeley) 3/7/91
* @(#)jobs.h 8.2 (Berkeley) 5/4/95
* $FreeBSD: src/bin/sh/jobs.h,v 1.18 2004/04/06 20:06:51 markm Exp $
*/
/* Mode argument to forkshell. Don't change FORK_FG or FORK_BG. */
@ -41,6 +38,7 @@
#define FORK_BG 1
#define FORK_NOJOB 2
#include <signal.h> /* for sig_atomic_t */
/*
* A job structure contains information about a job. A job is either a
@ -51,7 +49,7 @@
struct procstat {
pid_t pid; /* process id */
short status; /* status flags (defined above) */
int status; /* status flags (defined above) */
char *cmd; /* text of command being run */
};
@ -64,33 +62,41 @@ struct procstat {
struct job {
struct procstat ps0; /* status of process */
struct procstat *ps; /* status or processes when more than one */
pid_t nprocs; /* number of processes */
short nprocs; /* number of processes */
pid_t pgrp; /* process group of this job */
char state; /* true if job is finished */
char used; /* true if this entry is in used */
char changed; /* true if status has changed */
char foreground; /* true if running in the foreground */
#if JOBS
char jobctl; /* job running under job control */
struct job *next; /* job used after this one */
#endif
};
extern pid_t backgndpid; /* pid of last background process */
extern int job_warning; /* user was warned about stopped jobs */
extern int in_waitcmd; /* are we in waitcmd()? */
extern int in_dowait; /* are we in dowait()? */
extern volatile sig_atomic_t breakwaitcmd; /* break wait to process traps? */
#ifdef __STDC__
void setjobctl(int);
void showjobs(int);
int fgcmd(int, char **);
int bgcmd(int, char **);
int jobscmd(int, char **);
void showjobs(int, int, int);
int waitcmd(int, char **);
int jobidcmd(int, char **);
struct job *makejob(union node *, int);
int forkshell(struct job *, union node *, int);
int waitforjob(struct job *);
#else
void setjobctl();
void showjobs();
struct job *makejob();
int forkshell();
int waitforjob();
#endif
pid_t forkshell(struct job *, union node *, int);
int waitforjob(struct job *, int *);
int stoppedjobs(void);
char *commandtext(union node *);
#if ! JOBS
#define setjobctl(on) /* do nothing */
#endif
/*
* $PchId: jobs.h,v 1.4 2006/03/30 12:07:24 philip Exp $
*/

View file

@ -1,6 +1,6 @@
/*-
* Copyright (c) 1991 The Regents of the University of California.
* All rights reserved.
* Copyright (c) 1991, 1993
* The Regents of the University of California. All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* Kenneth Almquist.
@ -33,7 +33,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* @(#)machdep.h 5.1 (Berkeley) 3/7/91
* @(#)machdep.h 8.2 (Berkeley) 5/4/95
*/
/*
@ -47,5 +47,9 @@ union align {
char *cp;
};
#define ALIGN(nbytes) ((nbytes) + sizeof(union align) - 1 &~ (sizeof(union align) - 1))
#define ALIGN(nbytes) (((nbytes) + sizeof(union align) - 1) & ~(sizeof(union align) - 1))
#endif
/*
* $PchId: machdep.h,v 1.2 2001/05/15 16:36:26 philip Exp $
*/

View file

@ -1,6 +1,6 @@
/*-
* Copyright (c) 1991 The Regents of the University of California.
* All rights reserved.
* Copyright (c) 1991, 1993
* The Regents of the University of California. All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* Kenneth Almquist.
@ -13,10 +13,6 @@
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
@ -35,8 +31,14 @@
*/
#ifndef lint
static char sccsid[] = "@(#)mail.c 5.1 (Berkeley) 3/7/91";
#if 0
static char sccsid[] = "@(#)mail.c 8.2 (Berkeley) 5/4/95";
#endif
#endif /* not lint */
/*
#include <sys/cdefs.h>
__FBSDID("$FreeBSD: src/bin/sh/mail.c,v 1.13 2004/04/06 20:06:51 markm Exp $");
*/
/*
* Routines to check for mail. (Perhaps make part of main.c?)
@ -48,8 +50,10 @@ static char sccsid[] = "@(#)mail.c 5.1 (Berkeley) 3/7/91";
#include "output.h"
#include "memalloc.h"
#include "error.h"
#include "mail.h"
#include <sys/types.h>
#include <sys/stat.h>
#include <stdlib.h>
#define MAXMBOXES 10
@ -67,11 +71,12 @@ STATIC time_t mailtime[MAXMBOXES]; /* times of mailboxes */
*/
void
chkmail(silent) {
register int i;
chkmail(int silent)
{
int i;
char *mpath;
char *p;
register char *q;
char *q;
struct stackmark smark;
struct stat statb;
@ -91,18 +96,28 @@ chkmail(silent) {
if (q[-1] != '/')
abort();
q[-1] = '\0'; /* delete trailing '/' */
#ifdef notdef /* this is what the System V shell claims to do (it lies) */
if (stat(p, &statb) < 0)
statb.st_mtime = 0;
if (!silent
&& statb.st_size > 0
&& statb.st_mtime > mailtime[i]
&& statb.st_mtime > statb.st_atime
) {
out2str(pathopt? pathopt : "You have mail");
if (statb.st_mtime > mailtime[i] && ! silent) {
out2str(pathopt? pathopt : "you have mail");
out2c('\n');
}
mailtime[i] = statb.st_mtime;
#else /* this is what it should do */
if (stat(p, &statb) < 0)
statb.st_size = 0;
if (statb.st_size > mailtime[i] && ! silent) {
out2str(pathopt? pathopt : "you have mail");
out2c('\n');
}
mailtime[i] = statb.st_size;
#endif
}
nmboxes = i;
popstackmark(&smark);
}
/*
* $PchId: mail.c,v 1.5 2006/05/22 12:02:37 philip Exp $
*/

View file

@ -1,6 +1,6 @@
/*-
* Copyright (c) 1991 The Regents of the University of California.
* All rights reserved.
* Copyright (c) 1991, 1993
* The Regents of the University of California. All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* Kenneth Almquist.
@ -13,10 +13,6 @@
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
@ -33,11 +29,12 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* @(#)mail.h 5.1 (Berkeley) 3/7/91
* @(#)mail.h 8.2 (Berkeley) 5/4/95
* $FreeBSD: src/bin/sh/mail.h,v 1.8 2004/04/06 20:06:51 markm Exp $
*/
#ifdef __STDC__
void chkmail(int);
#else
void chkmail();
#endif
/*
* $PchId: mail.h,v 1.3 2006/03/30 11:53:44 philip Exp $
*/

View file

@ -1,6 +1,6 @@
/*-
* Copyright (c) 1991 The Regents of the University of California.
* All rights reserved.
* Copyright (c) 1991, 1993
* The Regents of the University of California. All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* Kenneth Almquist.
@ -13,10 +13,6 @@
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
@ -35,18 +31,29 @@
*/
#ifndef lint
char copyright[] =
"@(#) Copyright (c) 1991 The Regents of the University of California.\n\
All rights reserved.\n";
static char const copyright[] =
"@(#) Copyright (c) 1991, 1993\n\
The Regents of the University of California. All rights reserved.\n";
#endif /* not lint */
#ifndef lint
static char sccsid[] = "@(#)main.c 5.2 (Berkeley) 3/13/91";
#if 0
static char sccsid[] = "@(#)main.c 8.6 (Berkeley) 5/28/95";
#endif
#endif /* not lint */
/*
#include <sys/cdefs.h>
__FBSDID("$FreeBSD: src/bin/sh/main.c,v 1.26 2004/04/06 20:06:51 markm Exp $");
*/
#include <sys/types.h>
#include <stdio.h>
#include <signal.h>
#include <sys/stat.h>
#include <unistd.h>
#include <fcntl.h>
#include <locale.h>
#include <errno.h>
#include "shell.h"
#include "main.h"
#include "mail.h"
@ -54,38 +61,26 @@ static char sccsid[] = "@(#)main.c 5.2 (Berkeley) 3/13/91";
#include "output.h"
#include "parser.h"
#include "nodes.h"
#include "expand.h"
#include "eval.h"
#include "jobs.h"
#include "input.h"
#include "trap.h"
#if ATTY
#include "var.h"
#endif
#include "show.h"
#include "memalloc.h"
#include "error.h"
#include "init.h"
#include "mystring.h"
#define PROFILE 0
#include "exec.h"
#include "cd.h"
#include "builtins.h"
int rootpid;
int rootshell;
STATIC union node *curcmd;
STATIC union node *prevcmd;
extern int errno;
#if PROFILE
short profile_buf[16384];
extern int etext();
#endif
#ifdef __STDC__
STATIC void read_profile(char *);
char *getenv(char *);
#else
STATIC void read_profile();
char *getenv();
#endif
STATIC char *find_dot_file(char *);
/*
* Main routine. We initialize things, parse the arguments, execute
@ -95,16 +90,15 @@ char *getenv();
* is used to figure out how far we had gotten.
*/
main(argc, argv) char **argv; {
int
main(int argc, char *argv[])
{
struct jmploc jmploc;
struct stackmark smark;
volatile int state;
char *shinit, *home;
char *profile = NULL, *ashrc = NULL;
char *shinit;
#if PROFILE
monitor(4, etext, profile_buf, sizeof profile_buf, 50);
#endif
(void) setlocale(LC_ALL, "");
state = 0;
if (setjmp(jmploc.loc)) {
/*
@ -112,21 +106,32 @@ main(argc, argv) char **argv; {
* exception EXSHELLPROC to clean up before executing
* the shell procedure.
*/
if (exception == EXSHELLPROC) {
switch (exception) {
case EXSHELLPROC:
rootpid = getpid();
rootshell = 1;
minusc = NULL;
state = 3;
} else if (state == 0 || iflag == 0 || ! rootshell)
exitshell(2);
break;
case EXEXEC:
exitstatus = exerrno;
break;
case EXERROR:
exitstatus = 2;
break;
default:
break;
}
if (exception != EXSHELLPROC) {
if (state == 0 || iflag == 0 || ! rootshell)
exitshell(exitstatus);
}
reset();
#if ATTY
if (exception == EXINT
&& (! attyset() || equal(termval(), "emacs")))
#else
if (exception == EXINT)
#endif
{
if (exception == EXINT) {
out2c('\n');
flushout(&errout);
}
@ -151,57 +156,38 @@ main(argc, argv) char **argv; {
init();
setstackmark(&smark);
procargs(argc, argv);
if (eflag) eflag = 2; /* Truly enable [ex]flag after init. */
if (xflag) xflag = 2;
if (getpwd() == NULL && iflag)
out2str("sh: cannot determine working directory\n");
if (argv[0] && argv[0][0] == '-') {
state = 1;
read_profile("/etc/profile");
state1:
state = 2;
if ((home = getenv("HOME")) != NULL
&& (profile = (char *) malloc(strlen(home) + 10)) != NULL)
{
strcpy(profile, home);
strcat(profile, "/.profile");
read_profile(profile);
} else {
if (privileged == 0)
read_profile(".profile");
}
} else if ((sflag || minusc) && (shinit = getenv("SHINIT")) != NULL) {
state = 2;
evalstring(shinit);
else
read_profile("/etc/suid_profile");
}
state2:
if (profile != NULL) free(profile);
state = 3;
if (!argv[0] || argv[0][0] != '-') {
if ((home = getenv("HOME")) != NULL
&& (ashrc = (char *) malloc(strlen(home) + 8)) != NULL)
{
strcpy(ashrc, home);
strcat(ashrc, "/.ashrc");
read_profile(ashrc);
if (!privileged && iflag) {
if ((shinit = lookupvar("ENV")) != NULL && *shinit != '\0') {
state = 3;
read_profile(shinit);
}
}
state3:
if (ashrc != NULL) free(ashrc);
if (eflag) eflag = 1; /* Init done, enable [ex]flag */
if (xflag) xflag = 1;
exitstatus = 0; /* Init shouldn't influence initial $? */
state = 4;
if (minusc) {
evalstring(minusc);
}
if (sflag || minusc == NULL) {
state4:
state4: /* XXX ??? - why isn't this before the "if" statement */
cmdloop(1);
}
#if PROFILE
monitor(0);
#endif
exitshell(exitstatus);
/*NOTREACHED*/
return 0;
}
@ -211,52 +197,49 @@ state4:
*/
void
cmdloop(top) {
cmdloop(int top)
{
union node *n;
struct stackmark smark;
int inter;
int numeof;
int numeof = 0;
TRACE(("cmdloop(%d) called\n", top));
setstackmark(&smark);
numeof = 0;
for (;;) {
if (pendingsigs)
dotrap();
inter = 0;
if (iflag && top) {
inter++;
showjobs(1);
showjobs(1, 0, 0);
chkmail(0);
flushout(&output);
}
n = parsecmd(inter);
#if DEBUG
/* showtree(n); */
#endif
/* showtree(n); DEBUG */
if (n == NEOF) {
if (Iflag == 0 || numeof >= 50)
if (!top || numeof >= 50)
break;
out2str("\nUse \"exit\" to leave shell.\n");
if (!stoppedjobs()) {
if (!Iflag)
break;
out2str("\nUse \"exit\" to leave shell.\n");
}
numeof++;
} else if (n != NULL && nflag == 0) {
if (inter) {
INTOFF;
if (prevcmd)
freefunc(prevcmd);
prevcmd = curcmd;
curcmd = copyfunc(n);
INTON;
}
job_warning = (job_warning == 2) ? 1 : 0;
numeof = 0;
evaltree(n, 0);
#ifdef notdef
if (exitstatus) /*DEBUG*/
outfmt(&errout, "Exit status 0x%X\n", exitstatus);
#endif
}
popstackmark(&smark);
setstackmark(&smark);
if (evalskip == SKIPFILE) {
evalskip = 0;
break;
}
}
popstackmark(&smark); /* unnecessary */
popstackmark(&smark);
}
@ -266,9 +249,8 @@ cmdloop(top) {
*/
STATIC void
read_profile(name)
char *name;
{
read_profile(char *name)
{
int fd;
INTOFF;
@ -288,32 +270,63 @@ read_profile(name)
*/
void
readcmdfile(name)
char *name;
{
readcmdfile(char *name)
{
int fd;
INTOFF;
if ((fd = open(name, O_RDONLY)) >= 0)
setinputfd(fd, 1);
else
error("Can't open %s", name);
error("Can't open %s: %s", name, strerror(errno));
INTON;
cmdloop(0);
popfile();
}
/*
* Take commands from a file. To be compatable we should do a path
* search for the file, but a path search doesn't make any sense.
* Take commands from a file. To be compatible we should do a path
* search for the file, which is necessary to find sub-commands.
*/
dotcmd(argc, argv) char **argv; {
STATIC char *
find_dot_file(char *basename)
{
static char localname[FILENAME_MAX+1];
char *fullname;
char *path = pathval();
struct stat statb;
/* don't try this for absolute or relative paths */
if( strchr(basename, '/'))
return basename;
while ((fullname = padvance(&path, basename)) != NULL) {
strcpy(localname, fullname);
stunalloc(fullname);
if ((stat(fullname, &statb) == 0) && S_ISREG(statb.st_mode))
return localname;
}
return basename;
}
int
dotcmd(int argc, char **argv)
{
struct strlist *sp;
exitstatus = 0;
for (sp = cmdenviron; sp ; sp = sp->next)
setvareq(savestr(sp->text), VSTRFIXED|VTEXTFIXED);
if (argc >= 2) { /* That's what SVR2 does */
setinputfile(argv[1], 1);
commandname = argv[1];
char *fullname = find_dot_file(argv[1]);
setinputfile(fullname, 1);
commandname = fullname;
cmdloop(0);
popfile();
}
@ -321,40 +334,22 @@ dotcmd(argc, argv) char **argv; {
}
exitcmd(argc, argv) char **argv; {
int
exitcmd(int argc, char **argv)
{
extern int oexitstatus;
if (stoppedjobs())
return 0;
if (argc > 1)
exitstatus = number(argv[1]);
else
exitstatus = oexitstatus;
exitshell(exitstatus);
/*NOTREACHED*/
return 0;
}
lccmd(argc, argv) char **argv; {
if (argc > 1) {
defun(argv[1], prevcmd);
return 0;
} else {
INTOFF;
freefunc(curcmd);
curcmd = prevcmd;
prevcmd = NULL;
INTON;
evaltree(curcmd, 0);
return exitstatus;
}
}
#ifdef notdef
/*
* Should never be called.
* $PchId: main.c,v 1.5 2006/05/22 12:03:02 philip Exp $
*/
void
exit(exitstatus) {
_exit(exitstatus);
}
#endif

View file

@ -1,6 +1,6 @@
/*-
* Copyright (c) 1991 The Regents of the University of California.
* All rights reserved.
* Copyright (c) 1991, 1993
* The Regents of the University of California. All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* Kenneth Almquist.
@ -13,10 +13,6 @@
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
@ -33,16 +29,18 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* @(#)main.h 5.1 (Berkeley) 3/7/91
* @(#)main.h 8.2 (Berkeley) 5/4/95
* $FreeBSD: src/bin/sh/main.h,v 1.8 2004/04/06 20:06:51 markm Exp $
*/
extern int rootpid; /* pid of main shell */
extern int rootshell; /* true if we aren't a child of the main shell */
#ifdef __STDC__
void readcmdfile(char *);
void cmdloop(int);
#else
void readcmdfile();
void cmdloop();
#endif
int dotcmd(int, char **);
int exitcmd(int, char **);
/*
* $PchId: main.h,v 1.3 2006/03/30 11:43:59 philip Exp $
*/

View file

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

View file

@ -1,6 +1,6 @@
/*-
* Copyright (c) 1991 The Regents of the University of California.
* All rights reserved.
* Copyright (c) 1991, 1993
* The Regents of the University of California. All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* Kenneth Almquist.
@ -13,10 +13,6 @@
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
@ -33,13 +29,15 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* @(#)memalloc.h 5.1 (Berkeley) 3/7/91
* @(#)memalloc.h 8.2 (Berkeley) 5/4/95
* $FreeBSD: src/bin/sh/memalloc.h,v 1.9 2004/04/06 20:06:51 markm Exp $
*/
struct stackmark {
struct stack_block *stackp;
char *stacknxt;
int stacknleft;
struct stackmark *marknext;
};
@ -48,10 +46,8 @@ extern int stacknleft;
extern int sstrnleft;
extern int herefd;
#ifdef __STDC__
pointer ckmalloc(int);
pointer ckrealloc(pointer, int);
void free(pointer); /* defined in C library */
char *savestr(char *);
pointer stalloc(int);
void stunalloc(pointer);
@ -62,21 +58,6 @@ void grabstackblock(int);
char *growstackstr(void);
char *makestrspace(void);
void ungrabstackstr(char *, char *);
#else
pointer ckmalloc();
pointer ckrealloc();
void free(); /* defined in C library */
char *savestr();
pointer stalloc();
void stunalloc();
void setstackmark();
void popstackmark();
void growstackblock();
void grabstackblock();
char *growstackstr();
char *makestrspace();
void ungrabstackstr();
#endif
@ -84,7 +65,7 @@ void ungrabstackstr();
#define stackblocksize() stacknleft
#define STARTSTACKSTR(p) p = stackblock(), sstrnleft = stackblocksize()
#define STPUTC(c, p) (--sstrnleft >= 0? (*p++ = (c)) : (p = growstackstr(), *p++ = (c)))
#define CHECKSTRSPACE(n, p) if (sstrnleft < n) p = makestrspace(); else
#define CHECKSTRSPACE(n, p) { if (sstrnleft < n) p = makestrspace(); }
#define USTPUTC(c, p) (--sstrnleft, *p++ = (c))
#define STACKSTRNUL(p) (sstrnleft == 0? (p = growstackstr(), *p = '\0') : (*p = '\0'))
#define STUNPUTC(p) (++sstrnleft, --p)
@ -93,3 +74,7 @@ void ungrabstackstr();
#define grabstackstr(p) stalloc(stackblocksize() - sstrnleft)
#define ckfree(p) free((pointer)(p))
/*
* $PchId: memalloc.h,v 1.3 2006/03/30 11:39:41 philip Exp $
*/

View file

@ -1,6 +1,6 @@
/*-
* Copyright (c) 1991 The Regents of the University of California.
* All rights reserved.
* Copyright (c) 1991, 1993
* The Regents of the University of California. All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* Kenneth Almquist.
@ -13,10 +13,6 @@
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
@ -35,13 +31,32 @@
*/
#ifndef lint
static char sccsid[] = "@(#)miscbltin.c 5.2 (Berkeley) 3/13/91";
#if 0
static char sccsid[] = "@(#)miscbltin.c 8.4 (Berkeley) 5/4/95";
#endif
#endif /* not lint */
/*
#include <sys/cdefs.h>
__FBSDID("$FreeBSD: src/bin/sh/miscbltin.c,v 1.30 2004/04/06 20:06:51 markm Exp $");
*/
/*
* Miscelaneous builtins.
* Miscellaneous builtins.
*/
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/time.h>
#include <sys/select.h>
#include <time.h>
#include <unistd.h>
#include <ctype.h>
#include <errno.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <termios.h>
#include "shell.h"
#include "options.h"
#include "var.h"
@ -49,38 +64,71 @@ static char sccsid[] = "@(#)miscbltin.c 5.2 (Berkeley) 3/13/91";
#include "memalloc.h"
#include "error.h"
#include "mystring.h"
#include "builtins.h"
#undef eflag
extern char **argptr; /* argument list for builtin command */
/*
* The read builtin. The -e option causes backslashes to escape the
* following character.
* The read builtin. The -r option causes backslashes to be treated like
* ordinary characters.
*
* This uses unbuffered input, which may be avoidable in some cases.
*/
readcmd(argc, argv) char **argv; {
int
readcmd(int argc __unused, char **argv __unused)
{
char **ap;
int backslash;
char c;
int eflag;
int rflag;
char *prompt;
char *ifs;
char *p;
int startword;
int status;
int i;
struct timeval tv;
char *tvptr;
#ifndef __minix_vmd
fd_set ifds;
#endif
struct termios told, tnew;
int tsaved;
eflag = 0;
rflag = 0;
prompt = NULL;
while ((i = nextopt("ep:")) != '\0') {
if (i == 'p')
prompt = optarg;
else
eflag = 1;
tv.tv_sec = -1;
tv.tv_usec = 0;
while ((i = nextopt("erp:t:")) != '\0') {
switch(i) {
case 'p':
prompt = shoptarg;
break;
case 'e':
break;
case 'r':
rflag = 1;
break;
case 't':
tv.tv_sec = strtol(shoptarg, &tvptr, 0);
if (tvptr == shoptarg)
error("timeout value");
switch(*tvptr) {
case 0:
case 's':
break;
case 'h':
tv.tv_sec *= 60;
/* FALLTHROUGH */
case 'm':
tv.tv_sec *= 60;
break;
default:
error("timeout unit");
}
break;
}
}
if (prompt && isatty(0)) {
out2str(prompt);
@ -90,12 +138,45 @@ readcmd(argc, argv) char **argv; {
error("arg count");
if ((ifs = bltinlookup("IFS", 1)) == NULL)
ifs = nullstr;
if (tv.tv_sec >= 0) {
#ifdef __minix
abort();
#else
/*
* See if we can disable input processing; this will
* not give the desired result if we are in a pipeline
* and someone upstream is still in line-by-line mode.
*/
tsaved = 0;
if (tcgetattr(0, &told) == 0) {
memcpy(&tnew, &told, sizeof(told));
cfmakeraw(&tnew);
tcsetattr(0, TCSANOW, &tnew);
tsaved = 1;
}
/*
* Wait for something to become available.
*/
FD_ZERO(&ifds);
FD_SET(0, &ifds);
status = select(1, &ifds, NULL, NULL, &tv);
if (tsaved)
tcsetattr(0, TCSANOW, &told);
/*
* If there's nothing ready, return an error.
*/
if (status <= 0)
return(1);
#endif
}
status = 0;
startword = 1;
backslash = 0;
STARTSTACKSTR(p);
for (;;) {
if (read(0, &c, 1) != 1) {
if (read(STDIN_FILENO, &c, 1) != 1) {
status = 1;
break;
}
@ -107,7 +188,7 @@ readcmd(argc, argv) char **argv; {
STPUTC(c, p);
continue;
}
if (eflag && c == '\\') {
if (!rflag && c == '\\') {
backslash++;
continue;
}
@ -118,7 +199,7 @@ readcmd(argc, argv) char **argv; {
}
startword = 0;
if (backslash && c == '\\') {
if (read(0, &c, 1) != 1) {
if (read(STDIN_FILENO, &c, 1) != 1) {
status = 1;
break;
}
@ -142,25 +223,274 @@ readcmd(argc, argv) char **argv; {
umaskcmd(argc, argv) char **argv; {
int
umaskcmd(int argc __unused, char **argv)
{
char *ap;
int mask;
char *p;
int i;
int symbolic_mode = 0;
if ((p = argv[1]) == NULL) {
INTOFF;
mask = umask(0);
umask(mask);
INTON;
out1fmt("%.4o\n", mask); /* %#o might be better */
while ((i = nextopt("S")) != '\0') {
symbolic_mode = 1;
}
INTOFF;
mask = umask(0);
umask(mask);
INTON;
if ((ap = *argptr) == NULL) {
if (symbolic_mode) {
char u[4], g[4], o[4];
i = 0;
if ((mask & S_IRUSR) == 0)
u[i++] = 'r';
if ((mask & S_IWUSR) == 0)
u[i++] = 'w';
if ((mask & S_IXUSR) == 0)
u[i++] = 'x';
u[i] = '\0';
i = 0;
if ((mask & S_IRGRP) == 0)
g[i++] = 'r';
if ((mask & S_IWGRP) == 0)
g[i++] = 'w';
if ((mask & S_IXGRP) == 0)
g[i++] = 'x';
g[i] = '\0';
i = 0;
if ((mask & S_IROTH) == 0)
o[i++] = 'r';
if ((mask & S_IWOTH) == 0)
o[i++] = 'w';
if ((mask & S_IXOTH) == 0)
o[i++] = 'x';
o[i] = '\0';
out1fmt("u=%s,g=%s,o=%s\n", u, g, o);
} else {
out1fmt("%.4o\n", mask);
}
} else {
mask = 0;
do {
if ((unsigned)(i = *p - '0') >= 8)
error("Illegal number: %s", argv[1]);
mask = (mask << 3) + i;
} while (*++p != '\0');
umask(mask);
if (isdigit(*ap)) {
mask = 0;
do {
if (*ap >= '8' || *ap < '0')
error("Illegal number: %s", argv[1]);
mask = (mask << 3) + (*ap - '0');
} while (*++ap != '\0');
umask(mask);
} else {
void *set;
if ((set = setmode (ap)) == 0)
error("Illegal number: %s", ap);
mask = getmode (set, ~mask & 0777);
umask(~mask & 0777);
free(set);
}
}
return 0;
}
#ifdef __minix
struct rlimit
{
unsigned long rlim_cur; /* current (soft) limit */
unsigned long rlim_max; /* maximum value for rlim_cur */
};
#define RLIM_INFINITY (((unsigned long)1 << 31) - 1)
int getrlimit (int, struct rlimit *);
int setrlimit (int, const struct rlimit *);
int getrlimit(resource, rlp)
int resource;
struct rlimit *rlp;
{
errno= ENOSYS;
return -1;
}
int setrlimit(resource, rlp)
int resource;
const struct rlimit *rlp;
{
errno= ENOSYS;
return -1;
}
#endif
/*
* ulimit builtin
*
* This code, originally by Doug Gwyn, Doug Kingston, Eric Gisin, and
* Michael Rendell was ripped from pdksh 5.0.8 and hacked for use with
* ash by J.T. Conklin.
*
* Public domain.
*/
struct limits {
const char *name;
const char *units;
int cmd;
int factor; /* multiply by to get rlim_{cur,max} values */
char option;
};
static const struct limits limits[] = {
#ifdef RLIMIT_CPU
{ "cpu time", "seconds", RLIMIT_CPU, 1, 't' },
#endif
#ifdef RLIMIT_FSIZE
{ "file size", "512-blocks", RLIMIT_FSIZE, 512, 'f' },
#endif
#ifdef RLIMIT_DATA
{ "data seg size", "kbytes", RLIMIT_DATA, 1024, 'd' },
#endif
#ifdef RLIMIT_STACK
{ "stack size", "kbytes", RLIMIT_STACK, 1024, 's' },
#endif
#ifdef RLIMIT_CORE
{ "core file size", "512-blocks", RLIMIT_CORE, 512, 'c' },
#endif
#ifdef RLIMIT_RSS
{ "max memory size", "kbytes", RLIMIT_RSS, 1024, 'm' },
#endif
#ifdef RLIMIT_MEMLOCK
{ "locked memory", "kbytes", RLIMIT_MEMLOCK, 1024, 'l' },
#endif
#ifdef RLIMIT_NPROC
{ "max user processes", (char *)0, RLIMIT_NPROC, 1, 'u' },
#endif
#ifdef RLIMIT_NOFILE
{ "open files", (char *)0, RLIMIT_NOFILE, 1, 'n' },
#endif
#ifdef RLIMIT_VMEM
{ "virtual mem size", "kbytes", RLIMIT_VMEM, 1024, 'v' },
#endif
#ifdef RLIMIT_SWAP
{ "swap limit", "kbytes", RLIMIT_SWAP, 1024, 'w' },
#endif
#ifdef RLIMIT_SBSIZE
{ "sbsize", "bytes", RLIMIT_SBSIZE, 1, 'b' },
#endif
{ (char *) 0, (char *)0, 0, 0, '\0' }
};
int
ulimitcmd(int argc __unused, char **argv __unused)
{
int c;
intmax_t val = 0;
enum { SOFT = 0x1, HARD = 0x2 }
how = SOFT | HARD;
const struct limits *l;
int set, all = 0;
int optc, what;
struct rlimit limit;
what = 'f';
while ((optc = nextopt("HSatfdsmcnuvlb")) != '\0')
switch (optc) {
case 'H':
how = HARD;
break;
case 'S':
how = SOFT;
break;
case 'a':
all = 1;
break;
default:
what = optc;
}
for (l = limits; l->name && l->option != what; l++)
;
if (!l->name)
error("internal error (%c)", what);
set = *argptr ? 1 : 0;
if (set) {
char *p = *argptr;
if (all || argptr[1])
error("too many arguments");
if (strcmp(p, "unlimited") == 0)
val = RLIM_INFINITY;
else {
val = 0;
while ((c = *p++) >= '0' && c <= '9')
{
val = (val * 10) + (long)(c - '0');
if (val < 0)
break;
}
if (c)
error("bad number");
val *= l->factor;
}
}
if (all) {
for (l = limits; l->name; l++) {
char optbuf[40];
if (getrlimit(l->cmd, &limit) < 0)
error("can't get limit: %s", strerror(errno));
if (how & SOFT)
val = limit.rlim_cur;
else if (how & HARD)
val = limit.rlim_max;
if (l->units)
snprintf(optbuf, sizeof(optbuf),
"(%s, -%c) ", l->units, l->option);
else
snprintf(optbuf, sizeof(optbuf),
"(-%c) ", l->option);
out1fmt("%-18s %18s ", l->name, optbuf);
if (val == RLIM_INFINITY)
out1fmt("unlimited\n");
else
{
val /= l->factor;
out1fmt("%jd\n", (intmax_t)val);
}
}
return 0;
}
if (getrlimit(l->cmd, &limit) < 0)
error("can't get limit: %s", strerror(errno));
if (set) {
if (how & SOFT)
limit.rlim_cur = val;
if (how & HARD)
limit.rlim_max = val;
if (setrlimit(l->cmd, &limit) < 0)
error("bad limit: %s", strerror(errno));
} else {
if (how & SOFT)
val = limit.rlim_cur;
else if (how & HARD)
val = limit.rlim_max;
if (val == RLIM_INFINITY)
out1fmt("unlimited\n");
else
{
val /= l->factor;
out1fmt("%jd\n", (intmax_t)val);
}
}
return 0;
}
/*
* $PchId: miscbltin.c,v 1.7 2006/05/23 11:59:08 philip Exp $
*/

View file

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

View file

@ -1,6 +1,6 @@
/*-
* Copyright (c) 1991 The Regents of the University of California.
* All rights reserved.
* Copyright (c) 1991, 1993
* The Regents of the University of California. All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* Kenneth Almquist.
@ -13,10 +13,6 @@
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
@ -35,43 +31,51 @@
*/
#ifndef lint
char copyright[] =
"@(#) Copyright (c) 1991 The Regents of the University of California.\n\
All rights reserved.\n";
static char const copyright[] =
"@(#) Copyright (c) 1991, 1993\n\
The Regents of the University of California. All rights reserved.\n";
#endif /* not lint */
#ifndef lint
static char sccsid[] = "@(#)mkinit.c 5.3 (Berkeley) 3/13/91";
#if 0
static char sccsid[] = "@(#)mkinit.c 8.2 (Berkeley) 5/4/95";
#endif
#endif /* not lint */
/*
#include <sys/cdefs.h>
__FBSDID("$FreeBSD: src/bin/sh/mkinit.c,v 1.17 2004/04/06 20:06:51 markm Exp $");
*/
/*
* This program scans all the source files for code to handle various
* special events and combines this code into one file. This (allegedly)
* improves the structure of the program since there is no need for
* anyone outside of a module to know that that module performs special
* operations on particular events. The command is executed iff init.c
* is actually changed.
* operations on particular events.
*
* Usage: mkinit command sourcefile...
* Usage: mkinit sourcefile...
*/
#include <sys/cdefs.h>
#include <sys/types.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <unistd.h>
#include <errno.h>
#ifdef __minix
#define __unused
#endif
/*
* OUTFILE is the name of the output file. Output is initially written
* to the file OUTTEMP, which is then moved to OUTFILE if OUTTEMP and
* OUTFILE are different.
* to the file OUTTEMP, which is then moved to OUTFILE.
*/
#define OUTFILE "init.c"
#define OUTTEMP "init.c.new"
#define OUTOBJ "init.o"
/*
@ -89,7 +93,7 @@ struct text {
int nleft;
struct block *start;
struct block *last;
};
};
struct block {
struct block *next;
@ -105,7 +109,7 @@ struct event {
char *name; /* name of event (e.g. INIT) */
char *routine; /* name of routine called on event */
char *comment; /* comment describing routine */
struct text code; /* code for handling event */
struct text code; /* code for handling event */
};
@ -148,42 +152,35 @@ struct text decls; /* declarations */
int amiddecls; /* for formatting */
void readfile(), doevent(), doinclude(), dodecl(), output();
void addstr(), addchar(), writetext();
static void readfile(char *);
static int match(char *, char *);
static int gooddefine(char *);
static void doevent(struct event *, FILE *, char *);
static void doinclude(char *);
static void dodecl(char *, FILE *);
static void output(void);
static void addstr(char *, struct text *);
static void addchar(int, struct text *);
static void writetext(struct text *, FILE *);
static FILE *ckfopen(char *, char *);
static void *ckmalloc(int);
static char *savestr(char *);
static void error(char *);
#define equal(s1, s2) (strcmp(s1, s2) == 0)
FILE *ckfopen();
char *savestr();
void *ckmalloc __P((int));
void error();
main(argc, argv)
char **argv;
{
int
main(int argc __unused, char *argv[])
{
char **ap;
int fd;
char c;
if (argc < 2)
error("Usage: mkinit command file...");
header_files[0] = "\"shell.h\"";
header_files[1] = "\"mystring.h\"";
for (ap = argv + 2 ; *ap ; ap++)
for (ap = argv + 1 ; *ap ; ap++)
readfile(*ap);
output();
if (file_changed()) {
unlink(OUTFILE);
link(OUTTEMP, OUTFILE);
unlink(OUTTEMP);
} else {
unlink(OUTTEMP);
if (touch(OUTOBJ))
exit(0); /* no compilation necessary */
}
printf("%s\n", argv[1]);
execl("/bin/sh", "sh", "-c", argv[1], (char *)0);
error("Can't exec shell");
rename(OUTTEMP, OUTFILE);
exit(0);
}
@ -191,10 +188,9 @@ main(argc, argv)
* Parse an input file.
*/
void
readfile(fname)
char *fname;
{
static void
readfile(char *fname)
{
FILE *fp;
char line[1024];
struct event *ep;
@ -215,19 +211,31 @@ readfile(fname)
doinclude(line);
if (line[0] == 'M' && match("MKINIT", line))
dodecl(line, fp);
if (line[0] == '#' && gooddefine(line))
if (line[0] == '#' && gooddefine(line)) {
char *cp;
char line2[1024];
static const char undef[] = "#undef ";
strcpy(line2, line);
memcpy(line2, undef, sizeof(undef) - 1);
cp = line2 + sizeof(undef) - 1;
while(*cp && (*cp == ' ' || *cp == '\t'))
cp++;
while(*cp && *cp != ' ' && *cp != '\t' && *cp != '\n')
cp++;
*cp++ = '\n'; *cp = '\0';
addstr(line2, &defines);
addstr(line, &defines);
}
}
fclose(fp);
}
int
match(name, line)
char *name;
char *line;
{
register char *p, *q;
static int
match(char *name, char *line)
{
char *p, *q;
p = name, q = line;
while (*p) {
@ -240,11 +248,10 @@ match(name, line)
}
int
gooddefine(line)
char *line;
{
register char *p;
static int
gooddefine(char *line)
{
char *p;
if (! match("#define", line))
return 0; /* not a define */
@ -264,12 +271,9 @@ gooddefine(line)
}
void
doevent(ep, fp, fname)
register struct event *ep;
FILE *fp;
char *fname;
{
static void
doevent(struct event *ep, FILE *fp, char *fname)
{
char line[1024];
int indent;
char *p;
@ -304,13 +308,12 @@ doevent(ep, fp, fname)
}
void
doinclude(line)
char *line;
{
register char *p;
static void
doinclude(char *line)
{
char *p;
char *name;
register char **pp;
char **pp;
for (p = line ; *p != '"' && *p != '<' && *p != '\0' ; p++);
if (*p == '\0')
@ -329,13 +332,11 @@ doinclude(line)
}
void
dodecl(line1, fp)
char *line1;
FILE *fp;
{
static void
dodecl(char *line1, FILE *fp)
{
char line[1024];
register char *p, *q;
char *p, *q;
if (strcmp(line1, "MKINIT\n") == 0) { /* start of struct/union decl */
addchar('\n', &decls);
@ -350,7 +351,8 @@ dodecl(line1, fp)
if (! amiddecls)
addchar('\n', &decls);
q = NULL;
for (p = line1 + 6 ; *p != '=' && *p != '/' ; p++);
for (p = line1 + 6 ; *p && strchr("=/\n", *p) == NULL; p++)
continue;
if (*p == '=') { /* eliminate initialization */
for (q = p ; *q && *q != ';' ; q++);
if (*q == '\0')
@ -375,8 +377,9 @@ dodecl(line1, fp)
* Write the output to the file OUTTEMP.
*/
void
output() {
static void
output(void)
{
FILE *fp;
char **pp;
struct event *ep;
@ -392,7 +395,7 @@ output() {
for (ep = event ; ep->name ; ep++) {
fputs("\n\n\n", fp);
fputs(ep->comment, fp);
fprintf(fp, "\nvoid\n%s() {\n", ep->routine);
fprintf(fp, "\nvoid\n%s(void) {\n", ep->routine);
writetext(&ep->code, fp);
fprintf(fp, "}\n");
}
@ -400,62 +403,15 @@ output() {
}
/*
* Return true if the new output file is different from the old one.
*/
int
file_changed() {
register FILE *f1, *f2;
register int c;
if ((f1 = fopen(OUTFILE, "r")) == NULL
|| (f2 = fopen(OUTTEMP, "r")) == NULL)
return 1;
while ((c = getc(f1)) == getc(f2)) {
if (c == EOF)
return 0;
}
return 1;
}
/*
* Touch a file. Returns 0 on failure, 1 on success.
*/
int
touch(file)
char *file;
{
int fd;
char c;
if ((fd = open(file, O_RDWR)) < 0)
return 0;
if (read(fd, &c, 1) != 1) {
close(fd);
return 0;
}
lseek(fd, 0L, 0);
write(fd, &c, 1);
close(fd);
return 1;
}
/*
* A text structure is simply a block of text that is kept in memory.
* Addstr appends a string to the text struct, and addchar appends a single
* character.
*/
void
addstr(s, text)
register char *s;
register struct text *text;
{
static void
addstr(char *s, struct text *text)
{
while (*s) {
if (--text->nleft < 0)
addchar(*s++, text);
@ -465,10 +421,9 @@ addstr(s, text)
}
void
addchar(c, text)
register struct text *text;
{
static void
addchar(int c, struct text *text)
{
struct block *bp;
if (--text->nleft < 0) {
@ -487,11 +442,9 @@ addchar(c, text)
/*
* Write the contents of a text structure to a file.
*/
void
writetext(text, fp)
struct text *text;
FILE *fp;
{
static void
writetext(struct text *text, FILE *fp)
{
struct block *bp;
if (text->start != NULL) {
@ -501,47 +454,47 @@ writetext(text, fp)
}
}
FILE *
ckfopen(file, mode)
char *file;
char *mode;
{
static FILE *
ckfopen(char *file, char *mode)
{
FILE *fp;
if ((fp = fopen(file, mode)) == NULL) {
fprintf(stderr, "Can't open %s\n", file);
fprintf(stderr, "Can't open %s: %s\n", file, strerror(errno));
exit(2);
}
return fp;
}
void *
ckmalloc(nbytes) {
register char *p;
char *malloc();
static void *
ckmalloc(int nbytes)
{
char *p;
if ((p = malloc(nbytes)) == NULL)
error("Out of space");
return p;
}
char *
savestr(s)
char *s;
{
register char *p;
static char *
savestr(char *s)
{
char *p;
p = ckmalloc(strlen(s) + 1);
strcpy(p, s);
return p;
}
void
error(msg)
char *msg;
{
static void
error(char *msg)
{
if (curfile != NULL)
fprintf(stderr, "%s:%d: ", curfile, linno);
fprintf(stderr, "%s\n", msg);
exit(2);
}
/*
* $PchId: mkinit.c,v 1.6 2006/05/22 12:16:50 philip Exp $
*/

View file

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

View file

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

View file

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

View file

@ -1,7 +1,7 @@
#!/bin/sh -
#
# Copyright (c) 1991 The Regents of the University of California.
# All rights reserved.
# Copyright (c) 1991, 1993
# The Regents of the University of California. All rights reserved.
#
# This code is derived from software contributed to Berkeley by
# Kenneth Almquist.
@ -14,10 +14,6 @@
# 2. Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
# 3. All advertising materials mentioning features or use of this software
# must display the following acknowledgement:
# This product includes software developed by the University of
# California, Berkeley and its contributors.
# 4. Neither the name of the University nor the names of its contributors
# may be used to endorse or promote products derived from this software
# without specific prior written permission.
@ -34,7 +30,8 @@
# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
# SUCH DAMAGE.
#
# @(#)mktokens 5.1 (Berkeley) 3/7/91
# @(#)mktokens 8.1 (Berkeley) 5/31/93
# $FreeBSD: src/bin/sh/mktokens,v 1.9 2004/04/06 20:06:51 markm Exp $
# All calls to awk removed, because Minix bawk is deficient. (kjb)
@ -42,7 +39,9 @@
# token marks the end of a list. The third column is the name to print in
# error messages.
cat > /tmp/ka$$ <<\!
#temp=`/usr/bin/mktemp -t ka`
temp=/tmp/mkt$$
cat > $temp <<\!
TEOF 1 end of file
TNL 0 newline
TSEMI 0 ";"
@ -70,16 +69,17 @@ TBEGIN 0 "{"
TEND 1 "}"
TCASE 0 "case"
TESAC 1 "esac"
TNOT 0 "!"
!
nl=`wc -l /tmp/ka$$`
exec > token.def
nl=`wc -l $temp`
exec > token.h
i=0
while read line
do
set -$- $line
echo "#define $1 $i"
i=`expr $i + 1`
done </tmp/ka$$
done <$temp
echo '
/* Array indicating which tokens mark the end of a list */
const char tokendlist[] = {'
@ -87,18 +87,18 @@ while read line
do
set -$- $line
echo " $2,"
done </tmp/ka$$
done <$temp
echo '};
char *const tokname[] = {'
const char *const tokname[] = {'
sed -e 's/"/\\"/g' \
-e 's/[^ ]*[ ][ ]*[^ ]*[ ][ ]*\(.*\)/ "\1",/' \
/tmp/ka$$
$temp
echo '};
'
i=0
go=
sed 's/"//g' /tmp/ka$$ |
sed 's/"//g' $temp |
while read line
do
set -$- $line
@ -106,7 +106,7 @@ sed 's/"//g' /tmp/ka$$ |
then
echo "#define KWDOFFSET $i"
echo
echo "char *const parsekwd[] = {"
echo "const char *const parsekwd[] = {"
go=true
fi
if [ "$go" ]
@ -118,4 +118,7 @@ sed 's/"//g' /tmp/ka$$ |
echo ' 0
};'
rm /tmp/ka$$
rm $temp
#
# $PchId: mktokens,v 1.5 2006/05/22 12:43:35 philip Exp $

50
commands/ash/myhistedit.h Normal file
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.
* All rights reserved.
* Copyright (c) 1991, 1993
* The Regents of the University of California. All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* Kenneth Almquist.
@ -13,10 +13,6 @@
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
@ -35,8 +31,14 @@
*/
#ifndef lint
static char sccsid[] = "@(#)mystring.c 5.1 (Berkeley) 3/7/91";
#if 0
static char sccsid[] = "@(#)mystring.c 8.2 (Berkeley) 5/4/95";
#endif
#endif /* not lint */
/*
#include <sys/cdefs.h>
__FBSDID("$FreeBSD: src/bin/sh/mystring.c,v 1.13 2004/04/06 20:06:51 markm Exp $");
*/
/*
* String functions.
@ -44,12 +46,11 @@ static char sccsid[] = "@(#)mystring.c 5.1 (Berkeley) 3/7/91";
* equal(s1, s2) Return true if strings are equal.
* scopy(from, to) Copy a string.
* scopyn(from, to, n) Like scopy, but checks for overflow.
* strchr(s, c) Find first occurance of c in s.
* bcopy(from, to, n) Copy a block of memory.
* number(s) Convert a string of digits to an integer.
* is_number(s) Return true if s is a string of digits.
*/
#include <stdlib.h>
#include "shell.h"
#include "syntax.h"
#include "error.h"
@ -58,6 +59,14 @@ static char sccsid[] = "@(#)mystring.c 5.1 (Berkeley) 3/7/91";
char nullstr[1]; /* zero length string */
/*
* equal - #defined in mystring.h
*/
/*
* scopy - #defined in mystring.h
*/
/*
* scopyn - copy a string from "from" to "to", truncating the string
@ -66,11 +75,8 @@ char nullstr[1]; /* zero length string */
*/
void
scopyn(from, to, size)
register char const *from;
register char *to;
register int size;
{
scopyn(const char *from, char *to, int size)
{
while (--size > 0) {
if ((*to++ = *from++) == '\0')
@ -80,59 +86,13 @@ scopyn(from, to, size)
}
/*
* strchr - find first occurrence of a character in a string.
*/
#ifndef SYS5
char *
mystrchr(s, charwanted)
char const *s;
register char charwanted;
{
register char const *scan;
/*
* The odd placement of the two tests is so NUL is findable.
*/
for (scan = s ; *scan != charwanted ; ) /* ++ moved down for opt. */
if (*scan++ == '\0')
return NULL;
return (char *)scan;
}
#endif
/*
* bcopy - copy bytes
*
* This routine was derived from code by Henry Spencer.
*/
void
mybcopy(src, dst, length)
pointer dst;
const pointer src;
register int length;
{
register char *d = dst;
register char *s = src;
while (--length >= 0)
*d++ = *s++;
}
/*
* prefix -- see if pfx is a prefix of string.
*/
int
prefix(pfx, string)
register char const *pfx;
register char const *string;
{
prefix(const char *pfx, const char *string)
{
while (*pfx) {
if (*pfx++ != *string++)
return 0;
@ -147,12 +107,10 @@ prefix(pfx, string)
*/
int
number(s)
const char *s;
{
number(const char *s)
{
if (! is_number(s))
error2("Illegal number", (char *)s);
error("Illegal number: %s", (char *)s);
return atoi(s);
}
@ -163,12 +121,15 @@ number(s)
*/
int
is_number(p)
register const char *p;
{
is_number(const char *p)
{
do {
if (! is_digit(*p))
return 0;
} while (*++p != '\0');
return 1;
}
/*
* $PchId: mystring.c,v 1.4 2006/05/22 12:21:53 philip Exp $
*/

View file

@ -1,6 +1,6 @@
/*-
* Copyright (c) 1991 The Regents of the University of California.
* All rights reserved.
* Copyright (c) 1991, 1993
* The Regents of the University of California. All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* Kenneth Almquist.
@ -13,10 +13,6 @@
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
@ -33,39 +29,20 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* @(#)mystring.h 5.1 (Berkeley) 3/7/91
* @(#)mystring.h 8.2 (Berkeley) 5/4/95
* $FreeBSD: src/bin/sh/mystring.h,v 1.8 2004/04/06 20:06:51 markm Exp $
*/
#ifndef SYSV
#define strchr mystrchr
#endif
#include <string.h>
#ifdef __STDC__
void scopyn(const char *, char *, int);
char *strchr(const char *, int);
void mybcopy(const pointer, pointer, int);
int prefix(const char *, const char *);
int number(const char *);
int is_number(const char *);
int strcmp(const char *, const char *); /* from C library */
char *strcpy(char *, const char *); /* from C library */
int strlen(const char *); /* from C library */
char *strcat(char *, const char *); /* from C library */
char *strerror(int); /* from C library */
#else
void scopyn();
char *strchr();
void mybcopy();
int prefix();
int number();
int is_number();
int strcmp();
char *strcpy();
int strlen();
char *strcat();
char *strerror();
#endif
#define equal(s1, s2) (strcmp(s1, s2) == 0)
#define scopy(s1, s2) ((void)strcpy(s2, s1))
#define bcopy(src, dst, n) mybcopy((pointer)(src), (pointer)(dst), n)
/*
* $PchId: mystring.h,v 1.3 2006/03/29 15:49:08 philip Exp $
*/

View file

@ -1,6 +1,6 @@
/*-
* Copyright (c) 1991 The Regents of the University of California.
* All rights reserved.
* Copyright (c) 1991, 1993
* The Regents of the University of California. All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* Kenneth Almquist.
@ -13,10 +13,6 @@
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
@ -33,9 +29,11 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* @(#)nodes.c.pat 5.2 (Berkeley) 3/8/91
* @(#)nodes.c.pat 8.2 (Berkeley) 5/4/95
* $FreeBSD: src/bin/sh/nodes.c.pat,v 1.15 2004/04/06 20:06:51 markm Exp $
*/
#include <stdlib.h>
/*
* Routine for dealing with parsed shell commands.
*/
@ -43,35 +41,26 @@
#include "shell.h"
#include "nodes.h"
#include "memalloc.h"
#include "machdep.h"
#include "mystring.h"
int funcblocksize; /* size of structures in function */
int funcstringsize; /* size of strings in node */
#ifdef __STDC__
pointer funcblock; /* block to allocate function from */
#else
char *funcblock; /* block to allocate function from */
#ifndef __minix
#include <sys/param.h>
#endif
char *funcstring; /* block to allocate strings from */
#include "machdep.h"
STATIC int funcblocksize; /* size of structures in function */
STATIC int funcstringsize; /* size of strings in node */
STATIC pointer funcblock; /* block to allocate function from */
STATIC char *funcstring; /* block to allocate strings from */
%SIZES
#ifdef __STDC__
STATIC void calcsize(union node *);
STATIC void sizenodelist(struct nodelist *);
STATIC union node *copynode(union node *);
STATIC struct nodelist *copynodelist(struct nodelist *);
STATIC char *nodesavestr(char *);
#else
STATIC void calcsize();
STATIC void sizenodelist();
STATIC union node *copynode();
STATIC struct nodelist *copynodelist();
STATIC char *nodesavestr();
#endif
@ -80,86 +69,81 @@ STATIC char *nodesavestr();
*/
union node *
copyfunc(n)
union node *n;
{
if (n == NULL)
return NULL;
funcblocksize = 0;
funcstringsize = 0;
calcsize(n);
funcblock = ckmalloc(funcblocksize + funcstringsize);
funcstring = (char *)funcblock + funcblocksize;
return copynode(n);
copyfunc(union node *n)
{
if (n == NULL)
return NULL;
funcblocksize = 0;
funcstringsize = 0;
calcsize(n);
funcblock = ckmalloc(funcblocksize + funcstringsize);
funcstring = (char *)funcblock + funcblocksize;
return copynode(n);
}
STATIC void
calcsize(n)
union node *n;
{
%CALCSIZE
calcsize(union node *n)
{
%CALCSIZE
}
STATIC void
sizenodelist(lp)
struct nodelist *lp;
{
while (lp) {
funcblocksize += ALIGN(sizeof (struct nodelist));
calcsize(lp->n);
lp = lp->next;
}
sizenodelist(struct nodelist *lp)
{
while (lp) {
funcblocksize += ALIGN(sizeof(struct nodelist));
calcsize(lp->n);
lp = lp->next;
}
}
STATIC union node *
copynode(n)
union node *n;
{
union node *new;
copynode(union node *n)
{
union node *new;
%COPY
return new;
%COPY
return new;
}
STATIC struct nodelist *
copynodelist(lp)
struct nodelist *lp;
{
struct nodelist *start;
struct nodelist **lpp;
copynodelist(struct nodelist *lp)
{
struct nodelist *start;
struct nodelist **lpp;
lpp = &start;
while (lp) {
*lpp = funcblock;
*(char **)&funcblock += ALIGN(sizeof (struct nodelist));
(*lpp)->n = copynode(lp->n);
lp = lp->next;
lpp = &(*lpp)->next;
}
*lpp = NULL;
return start;
lpp = &start;
while (lp) {
*lpp = funcblock;
funcblock = (char *)funcblock + ALIGN(sizeof(struct nodelist));
(*lpp)->n = copynode(lp->n);
lp = lp->next;
lpp = &(*lpp)->next;
}
*lpp = NULL;
return start;
}
STATIC char *
nodesavestr(s)
char *s;
{
register char *p = s;
register char *q = funcstring;
char *rtn = funcstring;
nodesavestr(char *s)
{
char *p = s;
char *q = funcstring;
char *rtn = funcstring;
while (*q++ = *p++);
funcstring = q;
return rtn;
while ((*q++ = *p++) != '\0')
continue;
funcstring = q;
return rtn;
}
@ -169,9 +153,12 @@ nodesavestr(s)
*/
void
freefunc(n)
union node *n;
{
if (n)
ckfree(n);
freefunc(union node *n)
{
if (n)
ckfree(n);
}
/*
* $PchId: nodes.c.pat,v 1.5 2006/05/22 12:43:57 philip Exp $
*/

View file

@ -1,7 +1,6 @@
#!/bin/sh -
#
# Copyright (c) 1991 The Regents of the University of California.
# All rights reserved.
# Copyright (c) 1991, 1993
# The Regents of the University of California. All rights reserved.
#
# This code is derived from software contributed to Berkeley by
# Kenneth Almquist.
@ -14,10 +13,6 @@
# 2. Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
# 3. All advertising materials mentioning features or use of this software
# must display the following acknowledgement:
# This product includes software developed by the University of
# California, Berkeley and its contributors.
# 4. Neither the name of the University nor the names of its contributors
# may be used to endorse or promote products derived from this software
# without specific prior written permission.
@ -34,7 +29,8 @@
# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
# SUCH DAMAGE.
#
# @(#)nodetypes 5.1 (Berkeley) 3/7/91
# @(#)nodetypes 8.2 (Berkeley) 5/4/95
# $FreeBSD: src/bin/sh/nodetypes,v 1.9 2004/04/06 20:06:51 markm Exp $
# This file describes the nodes used in parse trees. Unindented lines
# contain a node type followed by a structure tag. Subsequent indented
@ -118,7 +114,9 @@ NARG narg # represents a word
NTO nfile # fd> fname
NFROM nfile # fd< fname
NFROMTO nfile # fd<> fname
NAPPEND nfile # fd>> fname
NCLOBBER nfile # fd>| fname
type int
next nodeptr # next redirection in list
fd int # file descriptor being redirected
@ -131,6 +129,8 @@ NFROMFD ndup # fd>&dupfd
next nodeptr # next redirection in list
fd int # file descriptor being redirected
dupfd int # file descriptor to duplicate
vname nodeptr # file name if fd>&$var
NHERE nhere # fd<<\!
NXHERE nhere # fd<<!
@ -138,3 +138,10 @@ NXHERE nhere # fd<<!
next nodeptr # next redirection in list
fd int # file descriptor being redirected
doc nodeptr # input to command (NARG node)
NNOT nnot # ! command (actually pipeline)
type int
com nodeptr
#
# $PchId: nodetypes,v 1.3 2006/03/29 15:43:35 philip Exp $

View file

@ -1,6 +1,6 @@
/*-
* Copyright (c) 1991 The Regents of the University of California.
* All rights reserved.
* Copyright (c) 1991, 1993
* The Regents of the University of California. All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* Kenneth Almquist.
@ -13,10 +13,6 @@
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
@ -35,8 +31,18 @@
*/
#ifndef lint
static char sccsid[] = "@(#)options.c 5.2 (Berkeley) 3/13/91";
#if 0
static char sccsid[] = "@(#)options.c 8.2 (Berkeley) 5/4/95";
#endif
#endif /* not lint */
/*
#include <sys/cdefs.h>
__FBSDID("$FreeBSD: src/bin/sh/options.c,v 1.21 2004/04/06 20:06:51 markm Exp $");
*/
#include <signal.h>
#include <unistd.h>
#include <stdlib.h>
#include "shell.h"
#define DEFINE_OPTIONS
@ -52,25 +58,24 @@ static char sccsid[] = "@(#)options.c 5.2 (Berkeley) 3/13/91";
#include "memalloc.h"
#include "error.h"
#include "mystring.h"
#include "builtins.h"
#if !defined(NO_HISTORY) && !defined(EDITLINE)
#include "myhistedit.h"
#endif
char *arg0; /* value of $0 */
struct shparam shellparam; /* current positional parameters */
char **argptr; /* argument list for builtin commands */
char *optarg; /* set by nextopt (like getopt) */
char *shoptarg; /* set by nextopt (like getopt) */
char *optptr; /* used by nextopt */
int editable; /* isatty(0) && isatty(1) */
char *minusc; /* argument to -c option */
#ifdef __STDC__
STATIC void options(int);
STATIC void minus_o(char *, int);
STATIC void setoption(int, int);
#else
STATIC void options();
STATIC void setoption();
#endif
STATIC int getopts(char *, char *, char **, char ***, char **);
/*
@ -78,46 +83,55 @@ STATIC void setoption();
*/
void
procargs(argc, argv)
char **argv;
{
char *p;
procargs(int argc, char **argv)
{
int i;
argptr = argv;
if (argc > 0)
argptr++;
for (p = optval ; p < optval + sizeof optval - 1 ; p++)
*p = 2;
for (i = 0; i < NOPTS; i++)
optlist[i].val = 2;
privileged = (getuid() != geteuid() || getgid() != getegid());
options(1);
if (*argptr == NULL && minusc == NULL)
sflag = 1;
editable = (isatty(0) && isatty(1));
if (iflag == 2 && sflag == 1 && editable)
if (iflag == 2 && sflag == 1 && isatty(0) && isatty(1))
iflag = 1;
if (jflag == 2)
jflag = iflag;
for (p = optval ; p < optval + sizeof optval - 1 ; p++)
if (*p == 2)
*p = 0;
if (mflag == 2)
mflag = iflag;
for (i = 0; i < NOPTS; i++)
if (optlist[i].val == 2)
optlist[i].val = 0;
arg0 = argv[0];
if (sflag == 0) {
arg0 = *argptr++;
if (minusc == NULL) {
commandname = arg0;
setinputfile(commandname, 0);
}
if (sflag == 0 && minusc == NULL) {
commandname = arg0 = *argptr++;
setinputfile(commandname, 0);
}
/* POSIX 1003.2: first arg after -c cmd is $0, remainder $1... */
if (argptr && minusc && *argptr)
arg0 = *argptr++;
shellparam.p = argptr;
shellparam.reset = 1;
/* assert(shellparam.malloc == 0 && shellparam.nparam == 0); */
while (*argptr) {
shellparam.nparam++;
argptr++;
}
setinteractive(iflag);
setjobctl(jflag);
optschanged();
}
void
optschanged(void)
{
setinteractive(iflag);
#if !defined(NO_HISTORY) && !defined(EDITLINE)
histedit();
#endif
setjobctl(mflag);
}
/*
* Process shell options. The global variable argptr contains a pointer
@ -125,8 +139,9 @@ procargs(argc, argv)
*/
STATIC void
options(cmdline) {
register char *p;
options(int cmdline)
{
char *p;
int val;
int c;
@ -136,14 +151,14 @@ options(cmdline) {
argptr++;
if ((c = *p++) == '-') {
val = 1;
if (p[0] == '\0' || p[0] == '-' && p[1] == '\0') {
if (p[0] == '\0' || (p[0] == '-' && p[1] == '\0')) {
if (!cmdline) {
/* "-" means turn off -x and -v */
if (p[0] == '\0')
xflag = vflag = 0;
/* "--" means reset params */
else if (*argptr == NULL)
setparam(argptr);
setparam(argptr);
}
break; /* "-" or "--" terminates options */
}
@ -166,26 +181,79 @@ options(cmdline) {
#ifdef NOHACK
break;
#endif
} else if (c == 'o') {
minus_o(*argptr, val);
if (*argptr)
argptr++;
} else {
if (c == 'p' && !val && privileged) {
(void) setuid(getuid());
(void) setgid(getgid());
}
setoption(c, val);
}
}
if (! cmdline)
break;
}
}
STATIC void
minus_o(char *name, int val)
{
int doneset, i;
if (name == NULL) {
if (val) {
/* "Pretty" output. */
out1str("Current option settings\n");
for (i = 0; i < NOPTS; i++)
out1fmt("%-16s%s\n", optlist[i].name,
optlist[i].val ? "on" : "off");
} else {
/* Output suitable for re-input to shell. */
for (doneset = i = 0; i < NOPTS; i++)
if (optlist[i].val) {
if (!doneset) {
out1str("set");
doneset = 1;
}
out1fmt(" -o %s", optlist[i].name);
}
if (doneset)
out1c('\n');
}
} else {
for (i = 0; i < NOPTS; i++)
if (equal(name, optlist[i].name)) {
if (!val && privileged && equal(name, "privileged")) {
(void) setuid(getuid());
(void) setgid(getgid());
}
setoption(optlist[i].letter, val);
return;
}
error("Illegal option -o %s", name);
}
}
STATIC void
setoption(flag, val)
char flag;
int val;
{
register char *p;
setoption(int flag, int val)
{
int i;
if ((p = strchr(optchar, flag)) == NULL)
error("Illegal option -%c", flag);
optval[p - optchar] = val;
for (i = 0; i < NOPTS; i++)
if (optlist[i].letter == flag) {
optlist[i].val = val;
if (val) {
/* #%$ hack for ksh semantics */
if (flag == 'V')
Eflag = 0;
else if (flag == 'E')
Vflag = 0;
}
return;
}
error("Illegal option -%c", flag);
}
@ -194,10 +262,12 @@ setoption(flag, val)
INCLUDE "options.h"
SHELLPROC {
char *p;
int i;
for (i = 0; i < NOPTS; i++)
optlist[i].val = 0;
optschanged();
for (p = optval ; p < optval + sizeof optval ; p++)
*p = 0;
}
#endif
@ -207,9 +277,8 @@ SHELLPROC {
*/
void
setparam(argv)
char **argv;
{
setparam(char **argv)
{
char **newparam;
char **ap;
int nparam;
@ -233,9 +302,8 @@ setparam(argv)
*/
void
freeparam(param)
struct shparam *param;
{
freeparam(struct shparam *param)
{
char **ap;
if (param->malloc) {
@ -251,7 +319,9 @@ freeparam(param)
* The shift builtin command.
*/
shiftcmd(argc, argv) char **argv; {
int
shiftcmd(int argc, char **argv)
{
int n;
char **ap1, **ap2;
@ -259,7 +329,7 @@ shiftcmd(argc, argv) char **argv; {
if (argc > 1)
n = number(argv[1]);
if (n > shellparam.nparam)
n = shellparam.nparam;
error("can't shift that many");
INTOFF;
shellparam.nparam -= n;
for (ap1 = shellparam.p ; --n >= 0 ; ap1++) {
@ -279,13 +349,14 @@ shiftcmd(argc, argv) char **argv; {
* The set command builtin.
*/
setcmd(argc, argv) char **argv; {
int
setcmd(int argc, char **argv)
{
if (argc == 1)
return showvarscmd(argc, argv);
INTOFF;
options(0);
setinteractive(iflag);
setjobctl(jflag);
optschanged();
if (*argptr != NULL) {
setparam(argptr);
}
@ -294,6 +365,15 @@ setcmd(argc, argv) char **argv; {
}
void
getoptsreset(const char *value)
{
if (number(value) == 1) {
shellparam.optnext = NULL;
shellparam.reset = 1;
}
}
/*
* The getopts builtin. Shellparam.optnext points to the next argument
* to be processed. Shellparam.optptr points to the next character to
@ -301,63 +381,127 @@ setcmd(argc, argv) char **argv; {
* then it's the first time getopts has been called.
*/
getoptscmd(argc, argv) char **argv; {
register char *p, *q;
char c;
int
getoptscmd(int argc, char **argv)
{
char **optbase = NULL;
if (argc < 3)
error("usage: getopts optstring var [arg]");
else if (argc == 3)
optbase = shellparam.p;
else
optbase = &argv[3];
if (shellparam.reset == 1) {
shellparam.optnext = optbase;
shellparam.optptr = NULL;
shellparam.reset = 0;
}
return getopts(argv[1], argv[2], optbase, &shellparam.optnext,
&shellparam.optptr);
}
STATIC int
getopts(char *optstr, char *optvar, char **optfirst, char ***optnext,
char **optptr)
{
char *p, *q;
char c = '?';
int done = 0;
int ind = 0;
int err = 0;
char s[10];
if (argc != 3)
error("Usage: getopts optstring var");
if (shellparam.optnext == NULL) {
shellparam.optnext = shellparam.p;
shellparam.optptr = NULL;
}
if ((p = shellparam.optptr) == NULL || *p == '\0') {
p = *shellparam.optnext;
if ((p = *optptr) == NULL || *p == '\0') {
/* Current word is done, advance */
if (*optnext == NULL)
return 1;
p = **optnext;
if (p == NULL || *p != '-' || *++p == '\0') {
atend:
fmtstr(s, 10, "%d", shellparam.optnext - shellparam.p + 1);
setvar("OPTIND", s, 0);
shellparam.optnext = NULL;
return 1;
ind = *optnext - optfirst + 1;
*optnext = NULL;
p = NULL;
done = 1;
goto out;
}
shellparam.optnext++;
(*optnext)++;
if (p[0] == '-' && p[1] == '\0') /* check for "--" */
goto atend;
}
c = *p++;
for (q = argv[1] ; *q != c ; ) {
for (q = optstr; *q != c; ) {
if (*q == '\0') {
out1fmt("Illegal option -%c\n", c);
if (optstr[0] == ':') {
s[0] = c;
s[1] = '\0';
err |= setvarsafe("OPTARG", s, 0);
}
else {
out1fmt("Illegal option -%c\n", c);
(void) unsetvar("OPTARG");
}
c = '?';
goto out;
goto bad;
}
if (*++q == ':')
q++;
}
if (*++q == ':') {
if (*p == '\0') {
if ((p = *shellparam.optnext) == NULL) {
out1fmt("No arg for -%c option\n", c);
c = '?';
goto out;
if (*p == '\0' && (p = **optnext) == NULL) {
if (optstr[0] == ':') {
s[0] = c;
s[1] = '\0';
err |= setvarsafe("OPTARG", s, 0);
c = ':';
}
shellparam.optnext++;
else {
out1fmt("No arg for -%c option\n", c);
(void) unsetvar("OPTARG");
c = '?';
}
goto bad;
}
setvar("OPTARG", p, 0);
p = "";
if (p == **optnext)
(*optnext)++;
setvarsafe("OPTARG", p, 0);
p = NULL;
}
else
setvarsafe("OPTARG", "", 0);
ind = *optnext - optfirst + 1;
goto out;
bad:
ind = 1;
*optnext = NULL;
p = NULL;
out:
shellparam.optptr = p;
*optptr = p;
fmtstr(s, sizeof(s), "%d", ind);
err |= setvarsafe("OPTIND", s, VNOFUNC);
s[0] = c;
s[1] = '\0';
setvar(argv[2], s, 0);
fmtstr(s, 10, "%d", shellparam.optnext - shellparam.p + 1);
setvar("OPTIND", s, 0);
return 0;
err |= setvarsafe(optvar, s, 0);
if (err) {
*optnext = NULL;
*optptr = NULL;
flushall();
exraise(EXERROR);
}
return done;
}
/*
* XXX - should get rid of. have all builtins use getopt(3). the
* library getopt must have the BSD extension static variable "optreset"
* otherwise it can't be used within the shell safely.
*
* Standard option processing (a la getopt) for builtin routines. The
* only argument that is passed to nextopt is the option string; the
* other arguments are unnecessary. It return the character, or '\0' on
@ -365,10 +509,9 @@ out:
*/
int
nextopt(optstring)
char *optstring;
{
register char *p, *q;
nextopt(char *optstring)
{
char *p, *q;
char c;
if ((p = optptr) == NULL || *p == '\0') {
@ -389,9 +532,13 @@ nextopt(optstring)
if (*++q == ':') {
if (*p == '\0' && (p = *argptr++) == NULL)
error("No arg for -%c option", c);
optarg = p;
shoptarg = p;
p = NULL;
}
optptr = p;
return c;
}
/*
* $PchId: options.c,v 1.5 2006/05/22 12:23:10 philip Exp $
*/

View file

@ -1,6 +1,6 @@
/*-
* Copyright (c) 1991 The Regents of the University of California.
* All rights reserved.
* Copyright (c) 1991, 1993
* The Regents of the University of California. All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* Kenneth Almquist.
@ -13,10 +13,6 @@
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
@ -33,38 +29,71 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* @(#)options.h 5.1 (Berkeley) 3/7/91
* @(#)options.h 8.2 (Berkeley) 5/4/95
* $FreeBSD: src/bin/sh/options.h,v 1.13 2004/04/06 20:06:51 markm Exp $
*/
struct shparam {
int nparam; /* number of positional parameters (without $0) */
char malloc; /* true if parameter list dynamicly allocated */
int nparam; /* # of positional parameters (without $0) */
unsigned char malloc; /* if parameter list dynamically allocated */
unsigned char reset; /* if getopts has been reset */
char **p; /* parameter list */
char **optnext; /* next parameter to be processed by getopts */
char *optptr; /* used by getopts */
char **optnext; /* next parameter to be processed by getopts */
char *optptr; /* used by getopts */
};
#define eflag optval[0]
#define fflag optval[1]
#define Iflag optval[2]
#define iflag optval[3]
#define jflag optval[4]
#define nflag optval[5]
#define sflag optval[6]
#define xflag optval[7]
#define zflag optval[8]
#define vflag optval[9]
#define eflag optlist[0].val
#define fflag optlist[1].val
#define Iflag optlist[2].val
#define iflag optlist[3].val
#define mflag optlist[4].val
#define nflag optlist[5].val
#define sflag optlist[6].val
#define xflag optlist[7].val
#define vflag optlist[8].val
#define Vflag optlist[9].val
#define Eflag optlist[10].val
#define Cflag optlist[11].val
#define aflag optlist[12].val
#define bflag optlist[13].val
#define uflag optlist[14].val
#define privileged optlist[15].val
#define Tflag optlist[16].val
#define Pflag optlist[17].val
#define NOPTS 10
#define NOPTS 18
struct optent {
const char *name;
const char letter;
char val;
};
#ifdef DEFINE_OPTIONS
const char optchar[NOPTS+1] = "efIijnsxzv"; /* shell flags */
char optval[NOPTS+1]; /* values of option flags */
struct optent optlist[NOPTS] = {
{ "errexit", 'e', 0 },
{ "noglob", 'f', 0 },
{ "ignoreeof", 'I', 0 },
{ "interactive",'i', 0 },
{ "monitor", 'm', 0 },
{ "noexec", 'n', 0 },
{ "stdin", 's', 0 },
{ "xtrace", 'x', 0 },
{ "verbose", 'v', 0 },
{ "vi", 'V', 0 },
{ "emacs", 'E', 0 },
{ "noclobber", 'C', 0 },
{ "allexport", 'a', 0 },
{ "notify", 'b', 0 },
{ "nounset", 'u', 0 },
{ "privileged", 'p', 0 },
{ "trapsasync", 'T', 0 },
{ "physical", 'P', 0 },
};
#else
extern const char optchar[NOPTS+1];
extern char optval[NOPTS+1];
extern struct optent optlist[NOPTS];
#endif
@ -72,19 +101,19 @@ extern char *minusc; /* argument to -c option */
extern char *arg0; /* $0 */
extern struct shparam shellparam; /* $@ */
extern char **argptr; /* argument list for builtin commands */
extern char *optarg; /* set by nextopt */
extern char *shoptarg; /* set by nextopt */
extern char *optptr; /* used by nextopt */
extern int editable; /* isatty(0) && isatty(1) */
#ifdef __STDC__
void procargs(int, char **);
void optschanged(void);
void setparam(char **);
void freeparam(struct shparam *);
int shiftcmd(int, char **);
int setcmd(int, char **);
int getoptscmd(int, char **);
int nextopt(char *);
#else
void procargs();
void setparam();
void freeparam();
int nextopt();
#endif
void getoptsreset(const char *);
/*
* $PchId: options.h,v 1.4 2006/03/29 15:37:43 philip Exp $
*/

View file

@ -1,6 +1,6 @@
/*-
* Copyright (c) 1991 The Regents of the University of California.
* All rights reserved.
* Copyright (c) 1991, 1993
* The Regents of the University of California. All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* Kenneth Almquist.
@ -13,10 +13,6 @@
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
@ -35,7 +31,7 @@
*/
#ifndef lint
static char sccsid[] = "@(#)output.c 5.1 (Berkeley) 3/7/91";
static char sccsid[] = "@(#)output.c 8.1 (Berkeley) 5/31/93";
#endif /* not lint */
/*
@ -55,12 +51,16 @@ static char sccsid[] = "@(#)output.c 5.1 (Berkeley) 3/7/91";
#include "output.h"
#include "memalloc.h"
#include "error.h"
#include "var.h"
#ifdef __STDC__
#include "stdarg.h"
#else
#include <varargs.h>
#endif
#include <errno.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#define OUTBUFSIZ BUFSIZ
@ -115,27 +115,63 @@ open_mem(block, length, file)
void
out1str(p)
char *p;
const char *p;
{
outstr(p, out1);
}
void
out1qstr(const char *p)
{
outqstr(p, out1);
}
void
out2str(p)
char *p;
{
out2str(const char *p)
{
outstr(p, out2);
}
void
outstr(p, file)
register char *p;
register const char *p;
register struct output *file;
{
while (*p)
outc(*p++, file);
if (file == out2)
flushout(file);
}
/* Like outstr(), but quote for re-input into the shell. */
void
outqstr(const char *p, struct output *file)
{
char ch;
if (p[strcspn(p, "|&;<>()$`\\\"'")] == '\0' && (!ifsset() ||
p[strcspn(p, ifsval())] == '\0')) {
outstr(p, file);
return;
}
out1c('\'');
while ((ch = *p++) != '\0') {
switch (ch) {
case '\'':
/*
* Can't quote single quotes inside single quotes;
* close them, write escaped single quote, open again.
*/
outstr("'\\''", file);
break;
default:
outc(ch, file);
}
}
out1c('\'');
}
@ -208,7 +244,8 @@ freestdout() {
#ifdef __STDC__
void
outfmt(struct output *file, char *fmt, ...) {
outfmt(struct output *file, const char *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
@ -218,7 +255,8 @@ outfmt(struct output *file, char *fmt, ...) {
void
out1fmt(char *fmt, ...) {
out1fmt(const char *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
@ -226,9 +264,20 @@ out1fmt(char *fmt, ...) {
va_end(ap);
}
void
dprintf(const char *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
doformat(out2, fmt, ap);
va_end(ap);
flushout(out2);
}
void
fmtstr(char *outbuf, int length, char *fmt, ...) {
fmtstr(char *outbuf, int length, const char *fmt, ...)
{
va_list ap;
struct output strout;
@ -275,6 +324,19 @@ out1fmt(va_alist)
va_end(ap);
}
void
dprintf(va_alist)
va_dcl
{
va_list ap;
char *fmt;
va_start(ap);
fmt = va_arg(ap, char *);
doformat(out2, fmt, ap);
va_end(ap);
flushout(out2);
}
void
fmtstr(va_alist)
@ -325,11 +387,8 @@ static const char digit[17] = "0123456789ABCDEF";
void
doformat(dest, f, ap)
register struct output *dest;
register char *f; /* format string */
va_list ap;
{
doformat(struct output *dest, const char *f, va_list ap)
{
register char c;
char temp[TEMPSIZE];
int flushleft;
@ -517,15 +576,6 @@ xwrite(fd, buf, nbytes)
}
}
/*
* Version of ioctl that retries after a signal is caught.
* $PchId: output.c,v 1.6 2006/05/22 12:46:03 philip Exp $
*/
int
xioctl(fd, request, arg) {
int i;
while ((i = ioctl(fd, request, arg)) == -1 && errno == EINTR);
return i;
}

View file

@ -1,6 +1,6 @@
/*-
* Copyright (c) 1991 The Regents of the University of California.
* All rights reserved.
* Copyright (c) 1991, 1993
* The Regents of the University of California. All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* Kenneth Almquist.
@ -13,10 +13,6 @@
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
@ -33,11 +29,14 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* @(#)output.h 5.1 (Berkeley) 3/7/91
* @(#)output.h 8.2 (Berkeley) 5/4/95
* $FreeBSD: src/bin/sh/output.h,v 1.13 2004/04/06 20:06:51 markm Exp $
*/
#ifndef OUTPUT_INCL
#include <stdarg.h>
struct output {
char *nextc;
int nleft;
@ -53,38 +52,27 @@ extern struct output memout;
extern struct output *out1;
extern struct output *out2;
#ifndef __printflike
#define __printflike(a,b)
#endif
#ifdef __STDC__
void outstr(char *, struct output *);
void out1str(char *);
void out2str(char *);
void outfmt(struct output *, char *, ...);
void out1fmt(char *, ...);
void fmtstr(char *, int, char *, ...);
/* void doformat(struct output *, char *, va_list); */
void doformat();
void open_mem(char *, int, struct output *);
void out1str(const char *);
void out1qstr(const char *);
void out2str(const char *);
void out2qstr(const char *);
void outstr(const char *, struct output *);
void outqstr(const char *, struct output *);
void emptyoutbuf(struct output *);
void flushall(void);
void flushout(struct output *);
void freestdout(void);
void outfmt(struct output *, const char *, ...) __printflike(2, 3);
void out1fmt(const char *, ...) __printflike(1, 2);
void dprintf(const char *, ...) __printflike(1, 2);
void fmtstr(char *, int, const char *, ...) __printflike(3, 4);
void doformat(struct output *, const char *, va_list) __printflike(2, 0);
int xwrite(int, char *, int);
int xioctl(int, int, int);
#else
void outstr();
void out1str();
void out2str();
void outfmt();
void out1fmt();
void fmtstr();
/* void doformat(); */
void doformat();
void emptyoutbuf();
void flushall();
void flushout();
void freestdout();
int xwrite();
int xioctl();
#endif
#define outc(c, file) (--(file)->nleft < 0? (emptyoutbuf(file), *(file)->nextc++ = (c)) : (*(file)->nextc++ = (c)))
#define out1c(c) outc(c, out1);
@ -92,3 +80,7 @@ int xioctl();
#define OUTPUT_INCL
#endif
/*
* $PchId: output.h,v 1.5 2006/05/23 12:04:54 philip Exp $
*/

File diff suppressed because it is too large Load diff

View file

@ -1,6 +1,6 @@
/*-
* Copyright (c) 1991 The Regents of the University of California.
* All rights reserved.
* Copyright (c) 1991, 1993
* The Regents of the University of California. All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* Kenneth Almquist.
@ -13,10 +13,6 @@
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
@ -33,7 +29,8 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* @(#)parser.h 5.1 (Berkeley) 3/7/91
* @(#)parser.h 8.3 (Berkeley) 5/4/95
* $FreeBSD: src/bin/sh/parser.h,v 1.10 2004/04/06 20:06:51 markm Exp $
*/
/* control characters in argument strings */
@ -42,18 +39,27 @@
#define CTLENDVAR '\203'
#define CTLBACKQ '\204'
#define CTLQUOTE 01 /* ored with CTLBACKQ code if in quotes */
/* CTLBACKQ | CTLQUOTE == '\205' */
#define CTLARI '\206'
#define CTLENDARI '\207'
#define CTLQUOTEMARK '\210'
/* variable substitution byte (follows CTLVAR) */
#define VSTYPE 07 /* type of variable substitution */
#define VSNUL 040 /* colon--treat the empty string as unset */
#define VSQUOTE 0100 /* inside double quotes--suppress splitting */
#define VSTYPE 0x0f /* type of variable substitution */
#define VSNUL 0x10 /* colon--treat the empty string as unset */
#define VSQUOTE 0x80 /* inside double quotes--suppress splitting */
/* values of VSTYPE field */
#define VSNORMAL 1 /* normal variable: $var or ${var} */
#define VSMINUS 2 /* ${var-text} */
#define VSPLUS 3 /* ${var+text} */
#define VSQUESTION 4 /* ${var?message} */
#define VSASSIGN 5 /* ${var=text} */
#define VSNORMAL 0x1 /* normal variable: $var or ${var} */
#define VSMINUS 0x2 /* ${var-text} */
#define VSPLUS 0x3 /* ${var+text} */
#define VSQUESTION 0x4 /* ${var?message} */
#define VSASSIGN 0x5 /* ${var=text} */
#define VSTRIMLEFT 0x6 /* ${var#pattern} */
#define VSTRIMLEFTMAX 0x7 /* ${var##pattern} */
#define VSTRIMRIGHT 0x8 /* ${var%pattern} */
#define VSTRIMRIGHTMAX 0x9 /* ${var%%pattern} */
#define VSLENGTH 0xa /* ${#var} */
/*
@ -63,12 +69,14 @@
*/
extern int tokpushback;
#define NEOF ((union node *)&tokpushback)
extern int whichprompt; /* 1 == PS1, 2 == PS2 */
#ifdef __STDC__
union node *parsecmd(int);
void fixredir(union node *, const char *, int);
int goodname(char *);
#else
union node *parsecmd();
int goodname();
#endif
char *getprompt(void *);
/*
* $PchId: parser.h,v 1.3 2006/03/29 14:33:35 philip Exp $
*/

View file

@ -1,6 +1,6 @@
/*-
* Copyright (c) 1991 The Regents of the University of California.
* All rights reserved.
* Copyright (c) 1991, 1993
* The Regents of the University of California. All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* Kenneth Almquist.
@ -13,10 +13,6 @@
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
@ -35,8 +31,23 @@
*/
#ifndef lint
static char sccsid[] = "@(#)redir.c 5.1 (Berkeley) 3/7/91";
#if 0
static char sccsid[] = "@(#)redir.c 8.2 (Berkeley) 5/4/95";
#endif
#endif /* not lint */
/*
#include <sys/cdefs.h>
__FBSDID("$FreeBSD: src/bin/sh/redir.c,v 1.26 2004/04/06 20:06:51 markm Exp $");
*/
#include <sys/types.h>
#include <sys/stat.h>
#include <signal.h>
#include <string.h>
#include <fcntl.h>
#include <errno.h>
#include <unistd.h>
#include <stdlib.h>
/*
* Code for dealing with input/output redirection.
@ -47,15 +58,10 @@ static char sccsid[] = "@(#)redir.c 5.1 (Berkeley) 3/7/91";
#include "jobs.h"
#include "expand.h"
#include "redir.h"
#include "eval.h"
#include "output.h"
#include "memalloc.h"
#include "error.h"
#include <sys/types.h>
#include <signal.h>
#include <fcntl.h>
#include <errno.h>
#include <limits.h>
#include "options.h"
#define EMPTY -2 /* marks an unused slot in redirtab */
@ -65,25 +71,21 @@ static char sccsid[] = "@(#)redir.c 5.1 (Berkeley) 3/7/91";
MKINIT
struct redirtab {
struct redirtab *next;
short renamed[10];
int renamed[10];
};
MKINIT struct redirtab *redirlist;
/* We keep track of whether or not fd0 has been redirected. This is for
background commands, where we want to redirect fd0 to /dev/null only
if it hasn't already been redirected. */
int fd0_redirected = 0;
/*
* We keep track of whether or not fd0 has been redirected. This is for
* background commands, where we want to redirect fd0 to /dev/null only
* if it hasn't already been redirected.
*/
STATIC int fd0_redirected = 0;
#ifdef __STDC__
STATIC void openredirect(union node *, char *);
STATIC void openredirect(union node *, char[10 ]);
STATIC int openhere(union node *);
#else
STATIC void openredirect();
STATIC int openhere();
#endif
/*
@ -95,15 +97,14 @@ STATIC int openhere();
*/
void
redirect(redir, flags)
union node *redir;
int flags;
{
redirect(union node *redir, int flags)
{
union node *n;
struct redirtab *sv;
struct redirtab *sv = NULL;
int i;
int fd;
char memory[10]; /* file descriptors to write to memory */
int try;
char memory[10]; /* file descriptors to write to memory */
for (i = 10 ; --i >= 0 ; )
memory[i] = 0;
@ -117,21 +118,38 @@ redirect(redir, flags)
}
for (n = redir ; n ; n = n->nfile.next) {
fd = n->nfile.fd;
try = 0;
if ((n->nfile.type == NTOFD || n->nfile.type == NFROMFD) &&
n->ndup.dupfd == fd)
continue; /* redirect from/to same file descriptor */
if ((flags & REDIR_PUSH) && sv->renamed[fd] == EMPTY) {
INTOFF;
if ((i = copyfd(fd, 10)) != EMPTY) {
again:
if ((i = fcntl(fd, F_DUPFD, 10)) == -1) {
switch (errno) {
case EBADF:
if (!try) {
openredirect(n, memory);
try++;
goto again;
}
/* FALLTHROUGH*/
default:
INTON;
error("%d: %s", fd, strerror(errno));
break;
}
}
if (!try) {
sv->renamed[fd] = i;
close(fd);
}
INTON;
if (i == EMPTY)
error("Out of file descriptors");
} else {
close(fd);
}
if (fd == 0)
fd0_redirected++;
openredirect(n, memory);
if (!try)
openredirect(n, memory);
}
if (memory[1])
out1 = &memout;
@ -141,16 +159,15 @@ redirect(redir, flags)
STATIC void
openredirect(redir, memory)
union node *redir;
char memory[10];
{
openredirect(union node *redir, char memory[10])
{
struct stat sb;
int fd = redir->nfile.fd;
char *fname;
int f;
/* Assume redirection succeeds. */
exitstatus = 0;
{ extern int exitstatus; exitstatus = 0; }
/*
* We suppress interrupts so that we won't leave open file
@ -163,34 +180,35 @@ openredirect(redir, memory)
case NFROM:
fname = redir->nfile.expfname;
if ((f = open(fname, O_RDONLY)) < 0)
error("cannot open %s: %s", fname, errmsg(errno, E_OPEN));
error("cannot open %s: %s", fname, strerror(errno));
movefd:
if (f != fd) {
copyfd(f, fd);
dup2(f, fd);
close(f);
}
break;
case NFROMTO:
fname = redir->nfile.expfname;
if ((f = open(fname, O_RDWR|O_CREAT, 0666)) < 0)
error("cannot create %s: %s", fname, strerror(errno));
goto movefd;
case NTO:
fname = redir->nfile.expfname;
#ifdef O_CREAT
if (Cflag && stat(fname, &sb) != -1 && S_ISREG(sb.st_mode))
error("cannot create %s: %s", fname,
strerror(EEXIST));
if ((f = open(fname, O_WRONLY|O_CREAT|O_TRUNC, 0666)) < 0)
error("cannot create %s: %s", fname, errmsg(errno, E_CREAT));
#else
if ((f = creat(fname, 0666)) < 0)
error("cannot create %s: %s", fname, errmsg(errno, E_CREAT));
#endif
error("cannot create %s: %s", fname, strerror(errno));
goto movefd;
case NCLOBBER:
fname = redir->nfile.expfname;
if ((f = open(fname, O_WRONLY|O_CREAT|O_TRUNC, 0666)) < 0)
error("cannot create %s: %s", fname, strerror(errno));
goto movefd;
case NAPPEND:
fname = redir->nfile.expfname;
#ifdef O_APPEND
if ((f = open(fname, O_WRONLY|O_CREAT|O_APPEND, 0666)) < 0)
error("cannot create %s: %s", fname, errmsg(errno, E_CREAT));
#else
if ((f = open(fname, O_WRONLY)) < 0
&& (f = creat(fname, 0666)) < 0)
error("cannot create %s: %s", fname, errmsg(errno, E_CREAT));
lseek(f, 0L, 2);
#endif
error("cannot create %s: %s", fname, strerror(errno));
goto movefd;
case NTOFD:
case NFROMFD:
@ -198,7 +216,9 @@ movefd:
if (memory[redir->ndup.dupfd])
memory[fd] = 1;
else
copyfd(redir->ndup.dupfd, fd);
dup2(redir->ndup.dupfd, fd);
} else {
close(fd);
}
break;
case NHERE:
@ -219,14 +239,13 @@ movefd:
*/
STATIC int
openhere(redir)
union node *redir;
{
openhere(union node *redir)
{
int pip[2];
int len;
int len = 0;
if (pipe(pip) < 0)
error("Pipe call failed");
error("Pipe call failed: %s", strerror(errno));
if (redir->type == NHERE) {
len = strlen(redir->nhere.doc->narg.text);
if (len <= PIPESIZE) {
@ -239,9 +258,7 @@ openhere(redir)
signal(SIGINT, SIG_IGN);
signal(SIGQUIT, SIG_IGN);
signal(SIGHUP, SIG_IGN);
#ifdef SIGTSTP
signal(SIGTSTP, SIG_IGN);
#endif
signal(SIGPIPE, SIG_DFL);
if (redir->type == NHERE)
xwrite(pip[1], redir->nhere.doc->narg.text, len);
@ -261,18 +278,20 @@ out:
*/
void
popredir() {
register struct redirtab *rp = redirlist;
popredir(void)
{
struct redirtab *rp = redirlist;
int i;
for (i = 0 ; i < 10 ; i++) {
if (rp->renamed[i] != EMPTY) {
if (i == 0)
fd0_redirected--;
close(i);
if (i == 0)
fd0_redirected--;
if (rp->renamed[i] >= 0) {
copyfd(rp->renamed[i], i);
dup2(rp->renamed[i], i);
close(rp->renamed[i]);
} else {
close(i);
}
}
}
@ -282,8 +301,6 @@ popredir() {
INTON;
}
/*
* Undo all redirections. Called on error or interrupt.
*/
@ -303,14 +320,21 @@ SHELLPROC {
#endif
/* Return true if fd 0 has already been redirected at least once. */
int
fd0_redirected_p(void)
{
return fd0_redirected != 0;
}
/*
* Discard all saved file descriptors.
*/
void
clearredir() {
register struct redirtab *rp;
clearredir(void)
{
struct redirtab *rp;
int i;
for (rp = redirlist ; rp ; rp = rp->next) {
@ -323,48 +347,6 @@ clearredir() {
}
}
/*
* Copy a file descriptor, like the F_DUPFD option of fcntl. Returns -1
* if the source file descriptor is closed, EMPTY if there are no unused
* file descriptors left.
* $PchId: redir.c,v 1.5 2006/05/22 12:27:37 philip Exp $
*/
int
copyfd(from, to) {
#ifdef F_DUPFD
int newfd;
newfd = fcntl(from, F_DUPFD, to);
if (newfd < 0 && errno == EMFILE)
return EMPTY;
return newfd;
#else
char toclose[32];
int i;
int newfd;
int e;
for (i = 0 ; i < to ; i++)
toclose[i] = 0;
INTOFF;
while ((newfd = dup(from)) >= 0 && newfd < to)
toclose[newfd] = 1;
e = errno;
for (i = 0 ; i < to ; i++) {
if (toclose[i])
close(i);
}
INTON;
if (newfd < 0 && e == EMFILE)
return EMPTY;
return newfd;
#endif
}
/* Return true if fd 0 has already been redirected at least once. */
int
fd0_redirected_p () {
return fd0_redirected != 0;
}

View file

@ -1,6 +1,6 @@
/*-
* Copyright (c) 1991 The Regents of the University of California.
* All rights reserved.
* Copyright (c) 1991, 1993
* The Regents of the University of California. All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* Kenneth Almquist.
@ -13,10 +13,6 @@
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
@ -33,24 +29,21 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* @(#)redir.h 5.1 (Berkeley) 3/7/91
* @(#)redir.h 8.2 (Berkeley) 5/4/95
* $FreeBSD: src/bin/sh/redir.h,v 1.10 2004/04/06 20:06:51 markm Exp $
*/
/* flags passed to redirect */
#define REDIR_PUSH 01 /* save previous values of file descriptors */
#define REDIR_BACKQ 02 /* save the command output in memory */
#ifdef __STDC__
union node;
void redirect(union node *, int);
void popredir(void);
void clearredir(void);
int copyfd(int, int);
int fd0_redirected_p(void);
#else
void redirect();
void popredir();
void clearredir();
int copyfd();
int fd0_redirected_p();
#endif
void clearredir(void);
/*
* $PchId: redir.h,v 1.3 2006/03/29 14:13:34 philip Exp $
*/

463
commands/ash/setmode.c Normal file
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.
* All rights reserved.
* Copyright (c) 1991, 1993
* The Regents of the University of California. All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* Kenneth Almquist.
@ -13,10 +13,6 @@
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
@ -33,19 +29,17 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* @(#)shell.h 5.4 (Berkeley) 4/12/91
* @(#)shell.h 8.2 (Berkeley) 5/4/95
* $FreeBSD: src/bin/sh/shell.h,v 1.17 2004/04/06 20:06:51 markm Exp $
*/
#include <sys/types.h> /* for mode_t */
/*
* The follow should be set to reflect the type of system you have:
* JOBS -> 1 if you have Berkeley job control, 0 otherwise.
* SYMLINKS -> 1 if your system includes symbolic links, 0 otherwise.
* DIRENT -> 1 if your system has the SVR3 directory(3X) routines.
* UDIR -> 1 if you want the shell to simulate the /u directory.
* TILDE -> 1 if you want the shell to expand ~logname.
* USEGETPW -> 1 if getpwnam() must be used to look up a name.
* ATTY -> 1 to include code for atty(1).
* SHORTNAMES -> 1 if your linker cannot handle long names.
* READLINE -> 1 if line editing by readline() should be enabled.
* define BSD if you are running 4.2 BSD or later.
* define SYSV if you are running under System V.
@ -56,52 +50,47 @@
* a quit signal will generate a core dump.
*/
#ifndef JOBS
#define JOBS 1
#endif
#ifndef BSD
#define BSD 1
#endif
#ifndef DEBUG
#define DEBUG 0
#endif
#define POSIX 1
#define JOBS 0
/* Set SYMLINKS to 0 by request of Giovanni Falzoni, who wrote the
* symlink patches for Minix; email to minix-devel-l of thu 3 nov.
/*
* Type of used arithmetics. SUSv3 requires us to have at least signed long.
*/
typedef long arith_t;
#define ARITH_FORMAT_STR "%ld"
#define atoarith_t(arg) strtol(arg, NULL, 0)
#define strtoarith_t(nptr, endptr, base) strtol(nptr, endptr, base)
#if 0
#define SYMLINKS defined(S_ISLNK)
#else
#define SYMLINKS 0
#endif
#define DIRENT 1
#define UDIR 0
#define TILDE 1
#define USEGETPW 0
#define ATTY 0
#define READLINE 1
#define HASHBANG 0
/* #define BSD */
#define POSIX 1
#define DEBUG 0
#ifdef __STDC__
typedef void *pointer;
#ifndef NULL
#define NULL (void *)0
#endif
#else /* not __STDC__ */
typedef char *pointer;
#ifndef NULL
#define NULL 0
#endif
#endif /* not __STDC__ */
#define STATIC /* empty */
#define MKINIT /* empty */
#include <sys/cdefs.h>
#include <sys/types.h>
#define STATIC static
#define MKINIT /* empty */
extern char nullstr[1]; /* null string */
#if DEBUG
#define TRACE(param) trace param
#define TRACE(param) sh_trace param
#else
#define TRACE(param)
#endif
#ifdef __minix
#define __unused
typedef long quad_t; /* XXX */
typedef unsigned long u_quad_t; /* XXX */
#endif
mode_t getmode(void *, int /* mode_t */);
void *setmode(char *);
/*
* $PchId: shell.h,v 1.7 2006/05/22 12:47:00 philip Exp $
*/

View file

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

42
commands/ash/show.h Normal file
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.
* All rights reserved.
* Copyright (c) 1991, 1993
* The Regents of the University of California. All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* Kenneth Almquist.
@ -13,10 +13,6 @@
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
@ -35,25 +31,45 @@
*/
#ifndef lint
static char sccsid[] = "@(#)trap.c 5.2 (Berkeley) 4/12/91";
#if 0
static char sccsid[] = "@(#)trap.c 8.5 (Berkeley) 6/5/95";
#endif
#endif /* not lint */
/*
#include <sys/cdefs.h>
__FBSDID("$FreeBSD: src/bin/sh/trap.c,v 1.29 2004/04/06 20:06:51 markm Exp $");
*/
#include <signal.h>
#include <unistd.h>
#include <stdlib.h>
#include "shell.h"
#include "main.h"
#include "nodes.h" /* for other headers */
#include "eval.h"
#include "jobs.h"
#include "show.h"
#include "options.h"
#include "syntax.h"
#include "signames.h"
#include "output.h"
#include "memalloc.h"
#include "error.h"
#include "trap.h"
#include "mystring.h"
#include <sys/types.h>
#include <signal.h>
#if !defined(NO_HISTORY) && !defined(EDITLINE)
#include "myhistedit.h"
#endif
#include "builtins.h"
#ifdef __minix
#define NO_SIGINTERRUPT
#define NO_SYS_SIGNAME
#define NO_SYS_SIGLIST
#endif
typedef void (*sig_T)(int);
/*
* Sigmode records the current value of the signal handlers for the various
@ -64,40 +80,130 @@ static char sccsid[] = "@(#)trap.c 5.2 (Berkeley) 4/12/91";
#define S_DFL 1 /* default signal handling (SIG_DFL) */
#define S_CATCH 2 /* signal is caught */
#define S_IGN 3 /* signal is ignored (SIG_IGN) */
#define S_HARD_IGN 4 /* signal is ignored permenantly */
#define S_HARD_IGN 4 /* signal is ignored permanently */
#define S_RESET 5 /* temporary - to reset a hard ignored sig */
extern char nullstr[1]; /* null string */
MKINIT char sigmode[_NSIG]; /* current value of signal */
int pendingsigs; /* indicates some signal received */
int is_interactive= -1; /* Shell is interactive */
int in_dotrap; /* do we execute in a trap handler? */
static char *volatile trap[_NSIG]; /* trap handler commands */
static volatile sig_atomic_t gotsig[_NSIG];
/* indicates specified signal received */
static int ignore_sigchld; /* Used while handling SIGCHLD traps. */
volatile sig_atomic_t gotwinch;
static int sigstring_to_signum (char *);
static void printsignals (void);
static int getsigaction(int, sig_T *);
static void onsig (int);
#ifdef NO_SIGINTERRUPT
static int siginterrupt (int,int);
#endif
static char *strsigname (int);
/*
* Map a string to a signal number.
*/
static int
sigstring_to_signum(char *sig)
{
if (is_number(sig)) {
int signo;
signo = atoi(sig);
return ((signo >= 0 && signo < _NSIG) ? signo : (-1));
} else if (strcasecmp(sig, "exit") == 0) {
return (0);
} else {
int n;
if (strncasecmp(sig, "sig", 3) == 0)
sig += 3;
for (n = 1; n < _NSIG; n++)
if (strcasecmp(strsigname(n), sig) == 0)
return (n);
}
return (-1);
}
/*
* Print a list of valid signal names.
*/
static void
printsignals(void)
{
int n, outlen;
outlen = 0;
for (n = 1; n < _NSIG; n++) {
if (strsigname(n)) {
out1fmt("%s", strsigname(n));
outlen += strlen(strsigname(n));
} else {
out1fmt("%d", n);
outlen += 3; /* good enough */
}
++outlen;
if (outlen > 70 || n == _NSIG - 1) {
out1str("\n");
outlen = 0;
} else {
out1c(' ');
}
}
}
char *trap[MAXSIG+1]; /* trap handler commands */
MKINIT char sigmode[MAXSIG]; /* current value of signal */
char gotsig[MAXSIG]; /* indicates specified signal received */
int pendingsigs; /* indicates some signal received */
/*
* The trap builtin.
*/
trapcmd(argc, argv) char **argv; {
int
trapcmd(int argc, char **argv)
{
char *action;
char **ap;
int signo;
if (argc <= 1) {
for (signo = 0 ; signo <= MAXSIG ; signo++) {
if (trap[signo] != NULL)
out1fmt("%d: %s\n", signo, trap[signo]);
for (signo = 0 ; signo < _NSIG ; signo++) {
if (trap[signo] != NULL) {
if (signo == 0) {
out1fmt("trap -- '%s' %s\n",
trap[signo], "exit");
} else if (strsigname(signo)) {
out1fmt("trap -- '%s' %s\n",
trap[signo], strsigname(signo));
} else {
out1fmt("trap -- '%s' %d\n",
trap[signo], signo);
}
}
}
return 0;
}
ap = argv + 1;
if (is_number(*ap))
action = NULL;
else
action = *ap++;
while (*ap) {
if ((signo = number(*ap)) < 0 || signo > MAXSIG)
error("%s: bad trap", *ap);
action = NULL;
if (*++argv && strcmp(*argv, "--") == 0)
argv++;
if (*argv && sigstring_to_signum(*argv) == -1) {
if ((*argv)[0] != '-') {
action = *argv;
argv++;
} else if ((*argv)[1] == '\0') {
argv++;
} else if ((*argv)[1] == 'l' && (*argv)[2] == '\0') {
printsignals();
return 0;
} else {
error("bad option %s", *argv);
}
}
while (*argv) {
if ((signo = sigstring_to_signum(*argv)) == -1)
error("bad signal %s", *argv);
INTOFF;
if (action)
action = savestr(action);
@ -107,22 +213,21 @@ trapcmd(argc, argv) char **argv; {
if (signo != 0)
setsignal(signo);
INTON;
ap++;
argv++;
}
return 0;
}
/*
* Clear traps on a fork.
*/
void
clear_traps() {
char **tp;
clear_traps(void)
{
char *volatile *tp;
for (tp = trap ; tp <= &trap[MAXSIG] ; tp++) {
for (tp = trap ; tp <= &trap[_NSIG - 1] ; tp++) {
if (*tp && **tp) { /* trap not NULL or SIG_IGN */
INTOFF;
ckfree(*tp);
@ -135,18 +240,16 @@ clear_traps() {
}
/*
* Set the signal handler for the specified signal. The routine figures
* out what it should be set to.
*/
int
setsignal(signo) {
void
setsignal(int signo)
{
int action;
sig_t sigact;
sig_T sig, sigact = SIG_DFL;
char *t;
extern void onsig();
if ((t = trap[signo]) == NULL)
action = S_DFL;
@ -154,11 +257,10 @@ setsignal(signo) {
action = S_CATCH;
else
action = S_IGN;
if (rootshell && action == S_DFL) {
if (action == S_DFL) {
switch (signo) {
case SIGINT:
if (iflag)
action = S_CATCH;
action = S_CATCH;
break;
case SIGQUIT:
#if DEBUG
@ -169,68 +271,103 @@ setsignal(signo) {
break;
}
#endif
/* FALLTHROUGH */
action = S_CATCH;
break;
case SIGTERM:
if (iflag)
if (rootshell && iflag)
action = S_IGN;
break;
#if JOBS
case SIGTSTP:
case SIGTTOU:
if (jflag)
if (rootshell && mflag)
action = S_IGN;
break;
#endif
#ifndef NO_HISTORY
case SIGWINCH:
if (rootshell && iflag)
action = S_CATCH;
break;
#endif
}
}
t = &sigmode[signo - 1];
if (*t == 0) { /* current setting unknown */
t = &sigmode[signo];
if (*t == 0) {
/*
* There is a race condition here if action is not S_IGN.
* A signal can be ignored that shouldn't be.
* current setting unknown
*/
if ((int)(sigact = signal(signo, SIG_IGN)) == -1)
error("Signal system call failed");
if (!getsigaction(signo, &sigact)) {
/*
* Pretend it worked; maybe we should give a warning
* here, but other shells don't. We don't alter
* sigmode, so that we retry every time.
*/
return;
}
if (sigact == SIG_IGN) {
*t = S_HARD_IGN;
if (mflag && (signo == SIGTSTP ||
signo == SIGTTIN || signo == SIGTTOU)) {
*t = S_IGN; /* don't hard ignore these */
} else
*t = S_HARD_IGN;
} else {
*t = S_IGN;
*t = S_RESET; /* force to be set */
}
}
if (*t == S_HARD_IGN || *t == action)
return 0;
return;
switch (action) {
case S_DFL: sigact = SIG_DFL; break;
case S_CATCH: sigact = onsig; break;
case S_IGN: sigact = SIG_IGN; break;
}
*t = action;
return (int)signal(signo, sigact);
sig = signal(signo, sigact);
if (sig != SIG_ERR && action == S_CATCH)
siginterrupt(signo, 1);
}
/*
* Return the current setting for sig w/o changing it.
*/
static int
getsigaction(int signo, sig_T *sigact)
{
struct sigaction sa;
if (sigaction(signo, (struct sigaction *)0, &sa) == -1)
return 0;
*sigact = (sig_T) sa.sa_handler;
return 1;
}
/*
* Ignore a signal.
*/
void
ignoresig(signo) {
if (sigmode[signo - 1] != S_IGN && sigmode[signo - 1] != S_HARD_IGN) {
ignoresig(int signo)
{
if (sigmode[signo] != S_IGN && sigmode[signo] != S_HARD_IGN) {
signal(signo, SIG_IGN);
}
sigmode[signo - 1] = S_HARD_IGN;
sigmode[signo] = S_HARD_IGN;
}
#ifdef mkinit
INCLUDE "signames.h"
INCLUDE <signal.h>
INCLUDE "trap.h"
SHELLPROC {
char *sm;
clear_traps();
for (sm = sigmode ; sm < sigmode + MAXSIG ; sm++) {
for (sm = sigmode ; sm < sigmode + _NSIG ; sm++) {
if (*sm == S_IGN)
*sm = S_HARD_IGN;
}
@ -238,82 +375,119 @@ SHELLPROC {
#endif
/*
* Signal handler.
*/
static void
onsig(int signo)
{
void
onsig(signo) {
#ifndef BSD
signal(signo, onsig);
#endif
if (signo == SIGINT && trap[SIGINT] == NULL) {
onint();
return;
}
gotsig[signo - 1] = 1;
pendingsigs++;
}
if (signo != SIGCHLD || !ignore_sigchld)
gotsig[signo] = 1;
pendingsigs++;
/* If we are currently in a wait builtin, prepare to break it */
if ((signo == SIGINT || signo == SIGQUIT) && in_waitcmd != 0)
breakwaitcmd = 1;
/*
* If a trap is set, not ignored and not the null command, we need
* to make sure traps are executed even when a child blocks signals.
*/
if (Tflag &&
trap[signo] != NULL &&
! trap[signo][0] == '\0' &&
! (trap[signo][0] == ':' && trap[signo][1] == '\0'))
breakwaitcmd = 1;
#ifndef NO_HISTORY
if (signo == SIGWINCH)
gotwinch = 1;
#endif
}
/*
* Called to execute a trap. Perhaps we should avoid entering new trap
* handlers while we are executing a trap handler.
*/
void
dotrap() {
dotrap(void)
{
int i;
int savestatus;
in_dotrap++;
for (;;) {
for (i = 1 ; ; i++) {
if (gotsig[i - 1])
for (i = 1; i < _NSIG; i++) {
if (gotsig[i]) {
gotsig[i] = 0;
if (trap[i]) {
/*
* Ignore SIGCHLD to avoid infinite
* recursion if the trap action does
* a fork.
*/
if (i == SIGCHLD)
ignore_sigchld++;
savestatus = exitstatus;
evalstring(trap[i]);
exitstatus = savestatus;
if (i == SIGCHLD)
ignore_sigchld--;
}
break;
if (i >= MAXSIG)
goto done;
}
}
gotsig[i - 1] = 0;
savestatus=exitstatus;
evalstring(trap[i]);
exitstatus=savestatus;
if (i >= _NSIG)
break;
}
done:
in_dotrap--;
pendingsigs = 0;
}
/*
* Controls whether the shell is interactive or not.
*/
int is_interactive;
void
setinteractive(on) {
setinteractive(int on)
{
if (on == is_interactive)
return;
setsignal(SIGINT);
setsignal(SIGQUIT);
setsignal(SIGTERM);
#ifndef NO_HISTORY
setsignal(SIGWINCH);
#endif
is_interactive = on;
}
/*
* Called to exit the shell.
*/
void
exitshell(status) {
exitshell(int status)
{
struct jmploc loc1, loc2;
char *p;
TRACE(("exitshell(%d) pid=%d\n", status, getpid()));
if (setjmp(loc1.loc)) goto l1;
if (setjmp(loc2.loc)) goto l2;
if (setjmp(loc1.loc)) {
goto l1;
}
if (setjmp(loc2.loc)) {
goto l2;
}
handler = &loc1;
if ((p = trap[0]) != NULL && *p != '\0') {
trap[0] = NULL;
@ -326,3 +500,85 @@ l1: handler = &loc2; /* probably unnecessary */
#endif
l2: _exit(status);
}
#ifdef NO_SIGINTERRUPT
static int siginterrupt(sig, flag)
int sig;
int flag;
{
return 0;
}
#endif
#ifdef NO_SYS_SIGNAME
static char *strsigname(sig)
int sig;
{
switch(sig)
{
case 0: return "Signal 0"; /* 0 */
case SIGHUP: return "hup"; /* 1 */
case SIGINT: return "int"; /* 2 */
case SIGQUIT: return "quit"; /* 3 */
case SIGILL: return "ill"; /* 4 */
case SIGTRAP: return "trap"; /* 5 */
case SIGABRT: return "abrt"; /* 6 */
#ifdef __minix_vmd
case SIGEMT: return "emt"; /* 7 */
#else
case SIGBUS: return "bus"; /* 7 */
#endif
case SIGFPE: return "fpe"; /* 8 */
case SIGKILL: return "kill"; /* 9 */
case SIGUSR1: return "usr1"; /* 10 */
case SIGSEGV: return "segv"; /* 11 */
case SIGUSR2: return "usr2"; /* 12 */
case SIGPIPE: return "pipe"; /* 13 */
case SIGALRM: return "alrm"; /* 14 */
case SIGTERM: return "term"; /* 15 */
#ifdef __minix_vmd
case 16: return "Signal 16"; /* 16 */
#else
case SIGEMT: return "emt"; /* 16 */
#endif
case SIGCHLD: return "chld"; /* 17 */
case SIGCONT: return "cont"; /* 18 */
case SIGSTOP: return "stop"; /* 19 */
case SIGTSTP: return "tstp"; /* 20 */
case SIGTTIN: return "ttin"; /* 21 */
case SIGTTOU: return "ttou"; /* 22 */
case SIGWINCH: return "winch"; /* 23 */
#ifdef __minix_vmd
case SIGFPEMU: return "fpemu"; /* 30 */
#endif
default: return "Signal n";
}
}
#else
static char *strsigname(sig)
int sig;
{
return sys_signame[sig];
}
#endif
#ifdef NO_SYS_SIGLIST
#include "signames.h"
char *strsiglist(sig)
int sig;
{
if (sig > MAXSIG)
return NULL;
return sigmesg[sig];
}
#else
char *strsiglist(sig)
int sig;
{
return sys_siglist[sig];
}
#endif
/*
* $PchId: trap.c,v 1.7 2006/05/23 11:56:21 philip Exp $
*/

View file

@ -1,6 +1,6 @@
/*-
* Copyright (c) 1991 The Regents of the University of California.
* All rights reserved.
* Copyright (c) 1991, 1993
* The Regents of the University of California. All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* Kenneth Almquist.
@ -13,10 +13,6 @@
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
@ -33,23 +29,24 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* @(#)trap.h 5.1 (Berkeley) 3/7/91
* @(#)trap.h 8.3 (Berkeley) 6/5/95
* $FreeBSD: src/bin/sh/trap.h,v 1.12 2004/04/06 20:06:51 markm Exp $
*/
extern int pendingsigs;
extern int in_dotrap;
extern int is_interactive;
extern volatile sig_atomic_t gotwinch;
#ifdef __STDC__
int trapcmd(int, char **);
void clear_traps(void);
int setsignal(int);
void setsignal(int);
void ignoresig(int);
void dotrap(void);
void setinteractive(int);
void exitshell(int);
#else
void clear_traps();
int setsignal();
void ignoresig();
void dotrap();
void setinteractive();
void exitshell();
#endif
char *strsiglist(int);
/*
* $PchId: trap.h,v 1.6 2006/05/22 12:48:30 philip Exp $
*/

View file

@ -1,6 +1,6 @@
/*-
* Copyright (c) 1991 The Regents of the University of California.
* All rights reserved.
* Copyright (c) 1991, 1993
* The Regents of the University of California. All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* Kenneth Almquist.
@ -13,10 +13,6 @@
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
@ -35,13 +31,27 @@
*/
#ifndef lint
static char sccsid[] = "@(#)var.c 5.3 (Berkeley) 4/12/91";
#if 0
static char sccsid[] = "@(#)var.c 8.3 (Berkeley) 5/4/95";
#endif
#endif /* not lint */
/*
#include <sys/cdefs.h>
__FBSDID("$FreeBSD: src/bin/sh/var.c,v 1.26.2.1 2004/09/30 04:41:55 des Exp $");
*/
#include <unistd.h>
#include <stdlib.h>
#ifndef NO_PATHS_H
#include <paths.h>
#endif
/*
* Shell variables.
*/
#include <locale.h>
#include "shell.h"
#include "output.h"
#include "expand.h"
@ -55,7 +65,16 @@ static char sccsid[] = "@(#)var.c 5.3 (Berkeley) 4/12/91";
#include "memalloc.h"
#include "error.h"
#include "mystring.h"
#include "parser.h"
#if !defined(NO_HISTORY) && !defined(EDITLINE)
#include "myhistedit.h"
#endif
#include "builtins.h"
#ifndef _PATH_DEFPATH
#define _PATH_DEFPATH "/usr/bin:/bin"
#endif
#define VTABSIZE 39
@ -64,48 +83,57 @@ struct varinit {
struct var *var;
int flags;
char *text;
void (*func)(const char *);
};
#if ATTY
struct var vatty;
#ifndef NO_HISTORY
struct var vhistsize;
#endif
struct var vifs;
struct var vmail;
struct var vmpath;
struct var vpath;
struct var vppid;
struct var vps1;
struct var vps2;
struct var vpse;
struct var vvers;
#if ATTY
struct var vterm;
#endif
STATIC struct var voptind;
const struct varinit varinit[] = {
#if ATTY
{&vatty, VSTRFIXED|VTEXTFIXED|VUNSET, "ATTY="},
STATIC const struct varinit varinit[] = {
#if !defined(NO_HISTORY) && !defined(EDITLINE)
{ &vhistsize, VSTRFIXED|VTEXTFIXED|VUNSET, "HISTSIZE=",
sethistsize },
#endif
{&vifs, VSTRFIXED|VTEXTFIXED, "IFS= \t\n"},
{&vmail, VSTRFIXED|VTEXTFIXED|VUNSET, "MAIL="},
{&vmpath, VSTRFIXED|VTEXTFIXED|VUNSET, "MAILPATH="},
{&vpath, VSTRFIXED|VTEXTFIXED, "PATH=:/bin:/usr/bin"},
/*
{ &vifs, VSTRFIXED|VTEXTFIXED, "IFS= \t\n",
NULL },
{ &vmail, VSTRFIXED|VTEXTFIXED|VUNSET, "MAIL=",
NULL },
{ &vmpath, VSTRFIXED|VTEXTFIXED|VUNSET, "MAILPATH=",
NULL },
{ &vpath, VSTRFIXED|VTEXTFIXED, "PATH=" _PATH_DEFPATH,
changepath },
{ &vppid, VSTRFIXED|VTEXTFIXED|VUNSET, "PPID=",
NULL },
/*
* vps1 depends on uid
*/
{&vps2, VSTRFIXED|VTEXTFIXED, "PS2=> "},
{&vpse, VSTRFIXED|VTEXTFIXED, "PSE=* "},
#if ATTY
{&vterm, VSTRFIXED|VTEXTFIXED|VUNSET, "TERM="},
#endif
{NULL, 0, NULL}
{ &vps2, VSTRFIXED|VTEXTFIXED, "PS2=> ",
NULL },
{ &vpse, VSTRFIXED|VTEXTFIXED|VUNSET, "PSE=",
NULL },
{ &voptind, VSTRFIXED|VTEXTFIXED, "OPTIND=1",
getoptsreset },
{ NULL, 0, NULL,
NULL }
};
struct var *vartab[VTABSIZE];
STATIC struct var *vartab[VTABSIZE];
STATIC void unsetvar __P((char *));
STATIC struct var **hashvar __P((char *));
STATIC int varequal __P((char *, char *));
STATIC struct var **hashvar(char *);
STATIC int varequal(char *, char *);
STATIC int localevar(char *);
/*
* Initialize the varable symbol tables and import the environment
@ -133,7 +161,9 @@ INIT {
*/
void
initvar() {
initvar(void)
{
char ppid[20];
const struct varinit *ip;
struct var *vp;
struct var **vpp;
@ -145,6 +175,7 @@ initvar() {
*vpp = vp;
vp->text = ip->text;
vp->flags = ip->flags;
vp->func = ip->func;
}
}
/*
@ -154,20 +185,48 @@ initvar() {
vpp = hashvar("PS1=");
vps1.next = *vpp;
*vpp = &vps1;
vps1.text = getuid() ? "PS1=$ " : "PS1=# ";
vps1.text = geteuid() ? "PS1=$ " : "PS1=# ";
vps1.flags = VSTRFIXED|VTEXTFIXED;
}
if ((vppid.flags & VEXPORT) == 0) {
fmtstr(ppid, sizeof(ppid), "%d", (int)getppid());
setvarsafe("PPID", ppid, 0);
}
}
/*
* Set the value of a variable. The flags argument is ored with the
* Safe version of setvar, returns 1 on success 0 on failure.
*/
int
setvarsafe(char *name, char *val, int flags)
{
struct jmploc jmploc;
struct jmploc *volatile savehandler = handler;
int err = 0;
#if __GNUC__
/* Avoid longjmp clobbering */
(void) &err;
#endif
if (setjmp(jmploc.loc))
err = 1;
else {
handler = &jmploc;
setvar(name, val, flags);
}
handler = savehandler;
return err;
}
/*
* Set the value of a variable. The flags argument is tored with the
* flags of the variable. If val is NULL, the variable is unset.
*/
void
setvar(name, val, flags)
char *name, *val;
{
setvar(char *name, char *val, int flags)
{
char *p, *q;
int len;
int namelen;
@ -176,8 +235,9 @@ setvar(name, val, flags)
isbad = 0;
p = name;
if (! is_name(*p++))
if (! is_name(*p))
isbad = 1;
p++;
for (;;) {
if (! is_in_name(*p)) {
if (*p == '\0' || *p == '=')
@ -188,7 +248,7 @@ setvar(name, val, flags)
}
namelen = p - name;
if (isbad)
error("%.*s: is read only", namelen, name);
error("%.*s: bad variable name", namelen, name);
len = namelen + 2; /* 2 is space for '=' and '\0' */
if (val == NULL) {
flags |= VUNSET;
@ -206,7 +266,26 @@ setvar(name, val, flags)
setvareq(nameeq, flags);
}
STATIC int
localevar(char *s)
{
static char *lnames[7] = {
"ALL", "COLLATE", "CTYPE", "MONETARY",
"NUMERIC", "TIME", NULL
};
char **ss;
if (*s != 'L')
return 0;
if (varequal(s + 1, "ANG"))
return 1;
if (strncmp(s + 1, "C_", 2) != 0)
return 0;
for (ss = lnames; *ss ; ss++)
if (varequal(s + 3, *ss))
return 1;
return 0;
}
/*
* Same as setvar except that the variable and value are passed in
@ -216,28 +295,42 @@ setvar(name, val, flags)
*/
void
setvareq(s, flags)
char *s;
{
setvareq(char *s, int flags)
{
struct var *vp, **vpp;
int len;
if (aflag)
flags |= VEXPORT;
vpp = hashvar(s);
for (vp = *vpp ; vp ; vp = vp->next) {
if (varequal(s, vp->text)) {
if (vp->flags & VREADONLY) {
int len = strchr(s, '=') - s;
len = strchr(s, '=') - s;
error("%.*s: is read only", len, s);
}
INTOFF;
if (vp == &vpath)
changepath(s + 5); /* 5 = strlen("PATH=") */
if (vp->func && (flags & VNOFUNC) == 0)
(*vp->func)(strchr(s, '=') + 1);
if ((vp->flags & (VTEXTFIXED|VSTACK)) == 0)
ckfree(vp->text);
vp->flags &=~ (VTEXTFIXED|VSTACK|VUNSET);
vp->flags &= ~(VTEXTFIXED|VSTACK|VUNSET);
vp->flags |= flags;
vp->text = s;
/*
* We could roll this to a function, to handle it as
* a regular variable function callback, but why bother?
*/
if (vp == &vmpath || (vp == &vmail && ! mpathset()))
chkmail(1);
if ((vp->flags & VEXPORT) && localevar(s)) {
putenv(s);
(void) setlocale(LC_ALL, "");
}
INTON;
return;
}
@ -247,7 +340,14 @@ setvareq(s, flags)
vp->flags = flags;
vp->text = s;
vp->next = *vpp;
vp->func = NULL;
INTOFF;
*vpp = vp;
if ((vp->flags & VEXPORT) && localevar(s)) {
putenv(s);
(void) setlocale(LC_ALL, "");
}
INTON;
}
@ -257,9 +357,8 @@ setvareq(s, flags)
*/
void
listsetvar(list)
struct strlist *list;
{
listsetvar(struct strlist *list)
{
struct strlist *lp;
INTOFF;
@ -276,9 +375,8 @@ listsetvar(list)
*/
char *
lookupvar(name)
char *name;
{
lookupvar(char *name)
{
struct var *v;
for (v = *hashvar(name) ; v ; v = v->next) {
@ -300,9 +398,8 @@ lookupvar(name)
*/
char *
bltinlookup(name, doall)
char *name;
{
bltinlookup(char *name, int doall)
{
struct strlist *sp;
struct var *v;
@ -312,8 +409,8 @@ bltinlookup(name, doall)
}
for (v = *hashvar(name) ; v ; v = v->next) {
if (varequal(v->text, name)) {
if (v->flags & VUNSET
|| ! doall && (v->flags & VEXPORT) == 0)
if ((v->flags & VUNSET)
|| (!doall && (v->flags & VEXPORT) == 0))
return NULL;
return strchr(v->text, '=') + 1;
}
@ -329,7 +426,8 @@ bltinlookup(name, doall)
*/
char **
environment() {
environment(void)
{
int nenv;
struct var **vpp;
struct var *vp;
@ -359,15 +457,14 @@ environment() {
*/
#ifdef mkinit
MKINIT void shprocvar();
SHELLPROC {
shprocvar();
}
#endif
void
shprocvar() {
shprocvar(void)
{
struct var **vpp;
struct var *vp, **prev;
@ -400,14 +497,21 @@ shprocvar() {
*/
int
showvarscmd(argc, argv) char **argv; {
showvarscmd(int argc __unused, char **argv __unused)
{
struct var **vpp;
struct var *vp;
const char *s;
for (vpp = vartab ; vpp < vartab + VTABSIZE ; vpp++) {
for (vp = *vpp ; vp ; vp = vp->next) {
if ((vp->flags & VUNSET) == 0)
out1fmt("%s\n", vp->text);
if (vp->flags & VUNSET)
continue;
for (s = vp->text; *s != '='; s++)
out1c(*s);
out1c('=');
out1qstr(s + 1);
out1c('\n');
}
}
return 0;
@ -420,15 +524,35 @@ showvarscmd(argc, argv) char **argv; {
*/
int
exportcmd(argc, argv) char **argv; {
exportcmd(int argc, char **argv)
{
struct var **vpp;
struct var *vp;
char *name;
char *p;
char *cmdname;
int ch, values;
int flag = argv[0][0] == 'r'? VREADONLY : VEXPORT;
cmdname = argv[0];
optreset = optind = 1;
opterr = 0;
values = 0;
while ((ch = getopt(argc, argv, "p")) != -1) {
switch (ch) {
case 'p':
values = 1;
break;
case '?':
default:
error("unknown option: -%c", optopt);
}
}
argc -= optind;
argv += optind;
listsetvar(cmdenviron);
if (argc > 1) {
if (argc != 0) {
while ((name = *argptr++) != NULL) {
if ((p = strchr(name, '=')) != NULL) {
p++;
@ -436,7 +560,12 @@ exportcmd(argc, argv) char **argv; {
vpp = hashvar(name);
for (vp = *vpp ; vp ; vp = vp->next) {
if (varequal(vp->text, name)) {
vp->flags |= flag;
if ((vp->flags & VEXPORT) && localevar(vp->text)) {
putenv(vp->text);
(void) setlocale(LC_ALL, "");
}
goto found;
}
}
@ -448,8 +577,16 @@ found:;
for (vpp = vartab ; vpp < vartab + VTABSIZE ; vpp++) {
for (vp = *vpp ; vp ; vp = vp->next) {
if (vp->flags & flag) {
if (values) {
out1str(cmdname);
out1c(' ');
}
for (p = vp->text ; *p != '=' ; p++)
out1c(*p);
if (values && !(vp->flags & VUNSET)) {
out1c('=');
out1qstr(p + 1);
}
out1c('\n');
}
}
@ -463,7 +600,9 @@ found:;
* The "local" command.
*/
localcmd(argc, argv) char **argv; {
int
localcmd(int argc __unused, char **argv __unused)
{
char *name;
if (! in_function())
@ -483,9 +622,8 @@ localcmd(argc, argv) char **argv; {
*/
void
mklocal(name)
char *name;
{
mklocal(char *name)
{
struct localvar *lvp;
struct var **vpp;
struct var *vp;
@ -493,8 +631,8 @@ mklocal(name)
INTOFF;
lvp = ckmalloc(sizeof (struct localvar));
if (name[0] == '-' && name[1] == '\0') {
lvp->text = ckmalloc(sizeof optval);
bcopy(optval, lvp->text, sizeof optval);
lvp->text = ckmalloc(sizeof optlist);
memcpy(lvp->text, optlist, sizeof optlist);
vp = NULL;
} else {
vpp = hashvar(name);
@ -527,7 +665,8 @@ mklocal(name)
*/
void
poplocalvars() {
poplocalvars(void)
{
struct localvar *lvp;
struct var *vp;
@ -535,10 +674,10 @@ poplocalvars() {
localvars = lvp->next;
vp = lvp->vp;
if (vp == NULL) { /* $- saved */
bcopy(lvp->text, optval, sizeof optval);
memcpy(optlist, lvp->text, sizeof optlist);
ckfree(lvp->text);
} else if ((lvp->flags & (VUNSET|VSTRFIXED)) == VUNSET) {
unsetvar(vp->text);
(void)unsetvar(vp->text);
} else {
if ((vp->flags & VTEXTFIXED) == 0)
ckfree(vp->text);
@ -550,7 +689,9 @@ poplocalvars() {
}
setvarcmd(argc, argv) char **argv; {
int
setvarcmd(int argc, char **argv)
{
if (argc <= 2)
return unsetcmd(argc, argv);
else if (argc == 3)
@ -567,14 +708,31 @@ setvarcmd(argc, argv) char **argv; {
* with the same name.
*/
unsetcmd(argc, argv) char **argv; {
int
unsetcmd(int argc __unused, char **argv __unused)
{
char **ap;
int i;
int flg_func = 0;
int flg_var = 0;
int ret = 0;
for (ap = argv + 1 ; *ap ; ap++) {
unsetfunc(*ap);
unsetvar(*ap);
while ((i = nextopt("vf")) != '\0') {
if (i == 'f')
flg_func = 1;
else
flg_var = 1;
}
return 0;
if (flg_func == 0 && flg_var == 0)
flg_var = 1;
for (ap = argptr; *ap ; ap++) {
if (flg_func)
ret |= unsetfunc(*ap);
if (flg_var)
ret |= unsetvar(*ap);
}
return ret;
}
@ -582,22 +740,25 @@ unsetcmd(argc, argv) char **argv; {
* Unset the specified variable.
*/
STATIC void
unsetvar(s)
char *s;
{
int
unsetvar(char *s)
{
struct var **vpp;
struct var *vp;
vpp = hashvar(s);
for (vp = *vpp ; vp ; vpp = &vp->next, vp = *vpp) {
if (varequal(vp->text, s)) {
if (vp->flags & VREADONLY)
return (1);
INTOFF;
if (*(strchr(vp->text, '=') + 1) != '\0'
|| vp->flags & VREADONLY) {
if (*(strchr(vp->text, '=') + 1) != '\0')
setvar(s, nullstr, 0);
if ((vp->flags & VEXPORT) && localevar(vp->text)) {
unsetenv(s);
setlocale(LC_ALL, "");
}
vp->flags &=~ VEXPORT;
vp->flags &= ~VEXPORT;
vp->flags |= VUNSET;
if ((vp->flags & VSTRFIXED) == 0) {
if ((vp->flags & VTEXTFIXED) == 0)
@ -606,9 +767,11 @@ unsetvar(s)
ckfree(vp);
}
INTON;
return;
return (0);
}
}
return (0);
}
@ -618,14 +781,13 @@ unsetvar(s)
*/
STATIC struct var **
hashvar(p)
register char *p;
{
hashvar(char *p)
{
unsigned int hashval;
hashval = *p << 4;
hashval = ((unsigned char) *p) << 4;
while (*p && *p != '=')
hashval += *p++;
hashval += (unsigned char) *p++;
return &vartab[hashval % VTABSIZE];
}
@ -638,9 +800,8 @@ hashvar(p)
*/
STATIC int
varequal(p, q)
register char *p, *q;
{
varequal(char *p, char *q)
{
while (*p == *q++) {
if (*p++ == '=')
return 1;
@ -649,3 +810,7 @@ varequal(p, q)
return 1;
return 0;
}
/*
* $PchId: var.c,v 1.5 2006/05/22 12:28:49 philip Exp $
*/

View file

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