New version of ash. From FreeBSD 5.4 via Minix-vmd.
This commit is contained in:
parent
3ea083b8d4
commit
7aa4c9ec2f
84 changed files with 8833 additions and 5442 deletions
|
@ -1,41 +1,61 @@
|
||||||
# Makefile for ash.
|
# Makefile for ash.
|
||||||
|
|
||||||
SRCS= builtins.c cd.c dirent.c error.c eval.c exec.c expand.c input.c \
|
SRCS= alias.c builtins.c cd.c error.c eval.c exec.c expand.c histedit.c \
|
||||||
|
input.c \
|
||||||
jobs.c mail.c main.c memalloc.c miscbltin.c mystring.c nodes.c \
|
jobs.c mail.c main.c memalloc.c miscbltin.c mystring.c nodes.c \
|
||||||
options.c parser.c redir.c show.c signames.c syntax.c trap.c \
|
options.c parser.c redir.c setmode.c show.c signames.c syntax.c \
|
||||||
|
trap.c \
|
||||||
output.c var.c
|
output.c var.c
|
||||||
|
|
||||||
OBJS= builtins.o cd.o dirent.o error.o eval.o exec.o expand.o input.o \
|
OBJS= alias.o builtins.o cd.o error.o eval.o exec.o expand.o histedit.o \
|
||||||
|
input.o \
|
||||||
jobs.o mail.o main.o memalloc.o miscbltin.o mystring.o nodes.o \
|
jobs.o mail.o main.o memalloc.o miscbltin.o mystring.o nodes.o \
|
||||||
options.o parser.o redir.o show.o signames.o syntax.o trap.o \
|
options.o parser.o redir.o setmode.o show.o signames.o syntax.o \
|
||||||
|
trap.o \
|
||||||
output.o var.o init.o \
|
output.o var.o init.o \
|
||||||
bltin/echo.o bltin/expr.o bltin/operators.o bltin/regexp.o
|
bltin/echo.o bltin/expr.o bltin/operators.o bltin/regexp.o \
|
||||||
|
arith.o arith_lex.o
|
||||||
|
|
||||||
#
|
LEX=flex
|
||||||
# Set READLINE in shell.h and add -ledit to LIBS if you want to use the
|
YACC=yacc
|
||||||
# editline package by Simmule Turner and Rich Salz. (The big, bloated
|
.c.o:
|
||||||
# and GPL contaminated FSF readline should work too.)
|
$(CC) $(CFLAGS) -c $< -o $@
|
||||||
#
|
|
||||||
CPPFLAGS= -DSHELL -I. -D_MINIX -D_POSIX_SOURCE
|
# Enable this line to disable command line editing
|
||||||
CFLAGS= -wo -i $(CPPFLAGS)
|
#EDIT=-DNO_HISTORY
|
||||||
LIBS= -ledit
|
# Enable this line to use the editline library instead of libedit
|
||||||
CC = exec cc
|
EDIT=-DEDITLINE
|
||||||
|
EDITLIB=-ledit
|
||||||
|
|
||||||
|
FLEXLIB=-lfl
|
||||||
|
|
||||||
|
# Enable this line if your system does not have a <paths.h>
|
||||||
|
NO_PATHS_H=-DNO_PATHS_H
|
||||||
|
|
||||||
|
# Enable this if you don't want job control
|
||||||
|
NO_JOBS=-DJOBS=0
|
||||||
|
MKB_NO_JOBS=-j
|
||||||
|
|
||||||
|
CPPFLAGS= -DSHELL -I. -D_MINIX $(EDIT) $(NO_PATHS_H) $(NO_JOBS)
|
||||||
|
CFLAGS= $(OPT) $(CPPFLAGS)
|
||||||
|
LIBS= $(EDITLIB) $(FLEXLIB)
|
||||||
|
|
||||||
CLEANFILES= $(OBJS) \
|
CLEANFILES= $(OBJS) \
|
||||||
builtins.c builtins.h init.c mkinit mknodes mksignames mksyntax \
|
arith.c arith_y.h arith_lex.c builtins.c builtins.h init.c \
|
||||||
nodes.c nodes.h signames.c signames.h syntax.c syntax.h token.def \
|
mkinit mknodes mksignames mksyntax \
|
||||||
|
nodes.c nodes.h signames.c signames.h syntax.c syntax.h token.h \
|
||||||
bltin/operators.h bltin/operators.c
|
bltin/operators.h bltin/operators.c
|
||||||
|
|
||||||
all: sh
|
all: sh
|
||||||
|
|
||||||
sh: $(OBJS)
|
sh: $(OBJS)
|
||||||
$(CC) $(CFLAGS) -o sh $(OBJS) $(LIBS)
|
$(CC) $(CFLAGS) -fnone -o sh $(OBJS) $(LIBS)
|
||||||
install -S 100k sh
|
|
||||||
|
|
||||||
install: /usr/bin/ash /usr/bin/sh /bin/sh /bin/bigsh
|
install: /usr/bin/ash /usr/bin/sh /bin/sh /usr/man/man1/ash.1 \
|
||||||
|
/usr/man/man1/echo.1 /usr/man/man1/expr.1
|
||||||
|
|
||||||
/usr/bin/ash: sh
|
/usr/bin/ash: sh
|
||||||
install -cs -o bin $? $@
|
install -c $? $@
|
||||||
|
|
||||||
/usr/bin/sh: /usr/bin/ash
|
/usr/bin/sh: /usr/bin/ash
|
||||||
install -l $? $@
|
install -l $? $@
|
||||||
|
@ -43,8 +63,14 @@ install: /usr/bin/ash /usr/bin/sh /bin/sh /bin/bigsh
|
||||||
/bin/sh: /usr/bin/ash
|
/bin/sh: /usr/bin/ash
|
||||||
install -lcs $? $@
|
install -lcs $? $@
|
||||||
|
|
||||||
/bin/bigsh: /usr/bin/ash
|
/usr/man/man1/ash.1: sh.1
|
||||||
install -S 1500000 -lcs $? $@
|
install -lc $? $@
|
||||||
|
|
||||||
|
/usr/man/man1/echo.1: bltin/echo.1
|
||||||
|
install -lc $? $@
|
||||||
|
|
||||||
|
/usr/man/man1/expr.1: bltin/expr.1
|
||||||
|
install -lc $? $@
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
rm -f $(CLEANFILES) sh core
|
rm -f $(CLEANFILES) sh core
|
||||||
|
@ -54,11 +80,18 @@ parser.o: token.def
|
||||||
token.def: mktokens
|
token.def: mktokens
|
||||||
sh mktokens
|
sh mktokens
|
||||||
|
|
||||||
builtins.c builtins.h: builtins.table shell.h
|
arith.c: arith.y
|
||||||
sh mkbuiltins shell.h builtins.table
|
$(YACC) -d $?
|
||||||
|
mv y.tab.c $@
|
||||||
|
mv y.tab.h arith_y.h
|
||||||
|
|
||||||
init.o: mkinit $(SRCS)
|
arith_lex.c: arith_lex.l
|
||||||
./mkinit '$(CC) -c $(CFLAGS) init.c' $(SRCS)
|
|
||||||
|
builtins.c builtins.h: builtins.def shell.h
|
||||||
|
sh mkbuiltins $(MKB_NO_JOBS) . shell.h builtins.def
|
||||||
|
|
||||||
|
init.c: mkinit $(SRCS)
|
||||||
|
./mkinit $(SRCS)
|
||||||
|
|
||||||
mkinit: mkinit.c
|
mkinit: mkinit.c
|
||||||
$(CC) $(CFLAGS) mkinit.c -o $@
|
$(CC) $(CFLAGS) mkinit.c -o $@
|
||||||
|
@ -81,20 +114,8 @@ syntax.c syntax.h: mksyntax
|
||||||
mksyntax: mksyntax.c parser.h
|
mksyntax: mksyntax.c parser.h
|
||||||
$(CC) $(CFLAGS) mksyntax.c -o $@
|
$(CC) $(CFLAGS) mksyntax.c -o $@
|
||||||
|
|
||||||
bltin/operators.h: bltin/mkexpr bltin/binary_op bltin/unary_op
|
bltin/operators.h: bltin/mkexpr bltin/unary_op bltin/binary_op
|
||||||
cd bltin && sh mkexpr
|
cd bltin && sh mkexpr unary_op binary_op
|
||||||
|
|
||||||
bltin/echo.o: bltin/echo.c
|
|
||||||
cd bltin && $(CC) -I.. $(CFLAGS) -c echo.c
|
|
||||||
|
|
||||||
bltin/expr.o: bltin/expr.c
|
|
||||||
cd bltin && $(CC) -I.. $(CFLAGS) -c expr.c
|
|
||||||
|
|
||||||
bltin/operators.o: bltin/operators.c
|
|
||||||
cd bltin && $(CC) -I.. $(CFLAGS) -c operators.c
|
|
||||||
|
|
||||||
bltin/regexp.o: bltin/regexp.c
|
|
||||||
cd bltin && $(CC) -I.. $(CFLAGS) -c regexp.c
|
|
||||||
|
|
||||||
# Dependencies you say? This will have to do.
|
# Dependencies you say? This will have to do.
|
||||||
$(OBJS): error.h eval.h exec.h expand.h init.h input.h \
|
$(OBJS): error.h eval.h exec.h expand.h init.h input.h \
|
||||||
|
@ -103,3 +124,6 @@ $(OBJS): error.h eval.h exec.h expand.h init.h input.h \
|
||||||
builtins.h nodes.h signames.h syntax.h
|
builtins.h nodes.h signames.h syntax.h
|
||||||
|
|
||||||
bltin/expr.o bltin/operators.o: bltin/operators.h
|
bltin/expr.o bltin/operators.o: bltin/operators.h
|
||||||
|
|
||||||
|
#
|
||||||
|
# $PchId: Makefile,v 1.4 2006/05/22 12:40:46 philip Exp $
|
||||||
|
|
|
@ -1,4 +1,13 @@
|
||||||
# @(#)TOUR 5.1 (Berkeley) 3/7/91
|
# @(#)TOUR 8.1 (Berkeley) 5/31/93
|
||||||
|
# $FreeBSD: src/bin/sh/TOUR,v 1.6 1999/08/27 23:15:07 peter Exp $
|
||||||
|
|
||||||
|
NOTE -- This is the original TOUR paper distributed with ash and
|
||||||
|
does not represent the current state of the shell. It is provided anyway
|
||||||
|
since it provides helpful information for how the shell is structured,
|
||||||
|
but be warned that things have changed -- the current shell is
|
||||||
|
still under development.
|
||||||
|
|
||||||
|
================================================================
|
||||||
|
|
||||||
A Tour through Ash
|
A Tour through Ash
|
||||||
|
|
||||||
|
@ -20,7 +29,7 @@ programs is:
|
||||||
mknodes nodetypes nodes.h nodes.c
|
mknodes nodetypes nodes.h nodes.c
|
||||||
mksignames - signames.h signames.c
|
mksignames - signames.h signames.c
|
||||||
mksyntax - syntax.h syntax.c
|
mksyntax - syntax.h syntax.c
|
||||||
mktokens - token.def
|
mktokens - token.h
|
||||||
bltin/mkexpr unary_op binary_op operators.h operators.c
|
bltin/mkexpr unary_op binary_op operators.h operators.c
|
||||||
|
|
||||||
There are undoubtedly too many of these. Mkinit searches all the
|
There are undoubtedly too many of these. Mkinit searches all the
|
||||||
|
@ -346,3 +355,6 @@ cause the preprocessor can't handle functions with a variable
|
||||||
number of arguments. Defining DEBUG also causes the shell to
|
number of arguments. Defining DEBUG also causes the shell to
|
||||||
generate a core dump if it is sent a quit signal. The tracing
|
generate a core dump if it is sent a quit signal. The tracing
|
||||||
code is in show.c.
|
code is in show.c.
|
||||||
|
|
||||||
|
#
|
||||||
|
# $PchId: TOUR,v 1.3 2006/03/31 11:33:46 philip Exp $
|
||||||
|
|
265
commands/ash/alias.c
Normal file
265
commands/ash/alias.c
Normal file
|
@ -0,0 +1,265 @@
|
||||||
|
/*-
|
||||||
|
* Copyright (c) 1993
|
||||||
|
* The Regents of the University of California. All rights reserved.
|
||||||
|
*
|
||||||
|
* This code is derived from software contributed to Berkeley by
|
||||||
|
* Kenneth Almquist.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
* 1. Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* 4. Neither the name of the University nor the names of its contributors
|
||||||
|
* may be used to endorse or promote products derived from this software
|
||||||
|
* without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||||
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||||
|
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
|
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||||
|
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||||
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||||
|
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||||
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||||
|
* SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef lint
|
||||||
|
#if 0
|
||||||
|
static char sccsid[] = "@(#)alias.c 8.3 (Berkeley) 5/4/95";
|
||||||
|
#endif
|
||||||
|
#endif /* not lint */
|
||||||
|
/*
|
||||||
|
#include <sys/cdefs.h>
|
||||||
|
__FBSDID("$FreeBSD: src/bin/sh/alias.c,v 1.18 2004/04/06 20:06:51 markm Exp $");
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include "shell.h"
|
||||||
|
#include "input.h"
|
||||||
|
#include "output.h"
|
||||||
|
#include "error.h"
|
||||||
|
#include "memalloc.h"
|
||||||
|
#include "mystring.h"
|
||||||
|
#include "alias.h"
|
||||||
|
#include "options.h" /* XXX for argptr (should remove?) */
|
||||||
|
#include "builtins.h"
|
||||||
|
|
||||||
|
#define ATABSIZE 39
|
||||||
|
|
||||||
|
STATIC struct alias *atab[ATABSIZE];
|
||||||
|
|
||||||
|
STATIC void setalias(char *, char *);
|
||||||
|
STATIC int unalias(char *);
|
||||||
|
STATIC struct alias **hashalias(char *);
|
||||||
|
|
||||||
|
STATIC
|
||||||
|
void
|
||||||
|
setalias(char *name, char *val)
|
||||||
|
{
|
||||||
|
struct alias *ap, **app;
|
||||||
|
|
||||||
|
app = hashalias(name);
|
||||||
|
for (ap = *app; ap; ap = ap->next) {
|
||||||
|
if (equal(name, ap->name)) {
|
||||||
|
INTOFF;
|
||||||
|
ckfree(ap->val);
|
||||||
|
ap->val = savestr(val);
|
||||||
|
INTON;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* not found */
|
||||||
|
INTOFF;
|
||||||
|
ap = ckmalloc(sizeof (struct alias));
|
||||||
|
ap->name = savestr(name);
|
||||||
|
/*
|
||||||
|
* XXX - HACK: in order that the parser will not finish reading the
|
||||||
|
* alias value off the input before processing the next alias, we
|
||||||
|
* dummy up an extra space at the end of the alias. This is a crock
|
||||||
|
* and should be re-thought. The idea (if you feel inclined to help)
|
||||||
|
* is to avoid alias recursions. The mechanism used is: when
|
||||||
|
* expanding an alias, the value of the alias is pushed back on the
|
||||||
|
* input as a string and a pointer to the alias is stored with the
|
||||||
|
* string. The alias is marked as being in use. When the input
|
||||||
|
* routine finishes reading the string, it marks the alias not
|
||||||
|
* in use. The problem is synchronization with the parser. Since
|
||||||
|
* it reads ahead, the alias is marked not in use before the
|
||||||
|
* resulting token(s) is next checked for further alias sub. The
|
||||||
|
* H A C K is that we add a little fluff after the alias value
|
||||||
|
* so that the string will not be exhausted. This is a good
|
||||||
|
* idea ------- ***NOT***
|
||||||
|
*/
|
||||||
|
#ifdef notyet
|
||||||
|
ap->val = savestr(val);
|
||||||
|
#else /* hack */
|
||||||
|
{
|
||||||
|
int len = strlen(val);
|
||||||
|
ap->val = ckmalloc(len + 2);
|
||||||
|
memcpy(ap->val, val, len);
|
||||||
|
ap->val[len] = ' '; /* fluff */
|
||||||
|
ap->val[len+1] = '\0';
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
ap->flag = 0;
|
||||||
|
ap->next = *app;
|
||||||
|
*app = ap;
|
||||||
|
INTON;
|
||||||
|
}
|
||||||
|
|
||||||
|
STATIC int
|
||||||
|
unalias(char *name)
|
||||||
|
{
|
||||||
|
struct alias *ap, **app;
|
||||||
|
|
||||||
|
app = hashalias(name);
|
||||||
|
|
||||||
|
for (ap = *app; ap; app = &(ap->next), ap = ap->next) {
|
||||||
|
if (equal(name, ap->name)) {
|
||||||
|
/*
|
||||||
|
* if the alias is currently in use (i.e. its
|
||||||
|
* buffer is being used by the input routine) we
|
||||||
|
* just null out the name instead of freeing it.
|
||||||
|
* We could clear it out later, but this situation
|
||||||
|
* is so rare that it hardly seems worth it.
|
||||||
|
*/
|
||||||
|
if (ap->flag & ALIASINUSE)
|
||||||
|
*ap->name = '\0';
|
||||||
|
else {
|
||||||
|
INTOFF;
|
||||||
|
*app = ap->next;
|
||||||
|
ckfree(ap->name);
|
||||||
|
ckfree(ap->val);
|
||||||
|
ckfree(ap);
|
||||||
|
INTON;
|
||||||
|
}
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return (1);
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef mkinit
|
||||||
|
INCLUDE "alias.h"
|
||||||
|
SHELLPROC {
|
||||||
|
rmaliases();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void
|
||||||
|
rmaliases(void)
|
||||||
|
{
|
||||||
|
struct alias *ap, *tmp;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
INTOFF;
|
||||||
|
for (i = 0; i < ATABSIZE; i++) {
|
||||||
|
ap = atab[i];
|
||||||
|
atab[i] = NULL;
|
||||||
|
while (ap) {
|
||||||
|
ckfree(ap->name);
|
||||||
|
ckfree(ap->val);
|
||||||
|
tmp = ap;
|
||||||
|
ap = ap->next;
|
||||||
|
ckfree(tmp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
INTON;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct alias *
|
||||||
|
lookupalias(char *name, int check)
|
||||||
|
{
|
||||||
|
struct alias *ap = *hashalias(name);
|
||||||
|
|
||||||
|
for (; ap; ap = ap->next) {
|
||||||
|
if (equal(name, ap->name)) {
|
||||||
|
if (check && (ap->flag & ALIASINUSE))
|
||||||
|
return (NULL);
|
||||||
|
return (ap);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return (NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* TODO - sort output
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
aliascmd(int argc, char **argv)
|
||||||
|
{
|
||||||
|
char *n, *v;
|
||||||
|
int ret = 0;
|
||||||
|
struct alias *ap;
|
||||||
|
|
||||||
|
if (argc == 1) {
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < ATABSIZE; i++)
|
||||||
|
for (ap = atab[i]; ap; ap = ap->next) {
|
||||||
|
if (*ap->name != '\0') {
|
||||||
|
out1fmt("alias %s=", ap->name);
|
||||||
|
out1qstr(ap->val);
|
||||||
|
out1c('\n');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
while ((n = *++argv) != NULL) {
|
||||||
|
if ((v = strchr(n+1, '=')) == NULL) /* n+1: funny ksh stuff */
|
||||||
|
if ((ap = lookupalias(n, 0)) == NULL) {
|
||||||
|
outfmt(out2, "alias: %s not found\n", n);
|
||||||
|
ret = 1;
|
||||||
|
} else {
|
||||||
|
out1fmt("alias %s=", n);
|
||||||
|
out1qstr(ap->val);
|
||||||
|
out1c('\n');
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
*v++ = '\0';
|
||||||
|
setalias(n, v);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return (ret);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
unaliascmd(int argc __unused, char **argv __unused)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
while ((i = nextopt("a")) != '\0') {
|
||||||
|
if (i == 'a') {
|
||||||
|
rmaliases();
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (i = 0; *argptr; argptr++)
|
||||||
|
i = unalias(*argptr);
|
||||||
|
|
||||||
|
return (i);
|
||||||
|
}
|
||||||
|
|
||||||
|
STATIC struct alias **
|
||||||
|
hashalias(char *p)
|
||||||
|
{
|
||||||
|
unsigned int hashval;
|
||||||
|
|
||||||
|
hashval = *p << 4;
|
||||||
|
while (*p)
|
||||||
|
hashval+= *p++;
|
||||||
|
return &atab[hashval % ATABSIZE];
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* $PchId: alias.c,v 1.5 2006/05/22 12:41:12 philip Exp $
|
||||||
|
*/
|
52
commands/ash/alias.h
Normal file
52
commands/ash/alias.h
Normal file
|
@ -0,0 +1,52 @@
|
||||||
|
/*-
|
||||||
|
* Copyright (c) 1993
|
||||||
|
* The Regents of the University of California. All rights reserved.
|
||||||
|
*
|
||||||
|
* This code is derived from software contributed to Berkeley by
|
||||||
|
* Kenneth Almquist.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
* 1. Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* 4. Neither the name of the University nor the names of its contributors
|
||||||
|
* may be used to endorse or promote products derived from this software
|
||||||
|
* without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||||
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||||
|
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
|
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||||
|
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||||
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||||
|
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||||
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||||
|
* SUCH DAMAGE.
|
||||||
|
*
|
||||||
|
* @(#)alias.h 8.2 (Berkeley) 5/4/95
|
||||||
|
* $FreeBSD: src/bin/sh/alias.h,v 1.8 2004/04/06 20:06:51 markm Exp $
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define ALIASINUSE 1
|
||||||
|
|
||||||
|
struct alias {
|
||||||
|
struct alias *next;
|
||||||
|
char *name;
|
||||||
|
char *val;
|
||||||
|
int flag;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct alias *lookupalias(char *, int);
|
||||||
|
int aliascmd(int, char **);
|
||||||
|
int unaliascmd(int, char **);
|
||||||
|
void rmaliases(void);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* $PchId: alias.h,v 1.4 2006/03/31 11:30:54 philip Exp $
|
||||||
|
*/
|
39
commands/ash/arith.h
Normal file
39
commands/ash/arith.h
Normal file
|
@ -0,0 +1,39 @@
|
||||||
|
/*-
|
||||||
|
* Copyright (c) 1995
|
||||||
|
* The Regents of the University of California. All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
* 1. Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* 4. Neither the name of the University nor the names of its contributors
|
||||||
|
* may be used to endorse or promote products derived from this software
|
||||||
|
* without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||||
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||||
|
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
|
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||||
|
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||||
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||||
|
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||||
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||||
|
* SUCH DAMAGE.
|
||||||
|
*
|
||||||
|
* @(#)arith.h 1.1 (Berkeley) 5/4/95
|
||||||
|
* $FreeBSD: src/bin/sh/arith.h,v 1.9 2004/04/06 20:06:51 markm Exp $
|
||||||
|
*/
|
||||||
|
|
||||||
|
int arith(char *);
|
||||||
|
int arith_assign(char *, arith_t);
|
||||||
|
int expcmd(int, char **);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* $PchId: arith.h,v 1.3 2006/03/31 11:25:25 philip Exp $
|
||||||
|
*/
|
366
commands/ash/arith.y
Normal file
366
commands/ash/arith.y
Normal file
|
@ -0,0 +1,366 @@
|
||||||
|
%{
|
||||||
|
/*-
|
||||||
|
* Copyright (c) 1993
|
||||||
|
* The Regents of the University of California. All rights reserved.
|
||||||
|
*
|
||||||
|
* This code is derived from software contributed to Berkeley by
|
||||||
|
* Kenneth Almquist.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
* 1. Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* 4. Neither the name of the University nor the names of its contributors
|
||||||
|
* may be used to endorse or promote products derived from this software
|
||||||
|
* without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||||
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||||
|
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
|
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||||
|
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||||
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||||
|
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||||
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||||
|
* SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
#ifndef lint
|
||||||
|
static char sccsid[] = "@(#)arith.y 8.3 (Berkeley) 5/4/95";
|
||||||
|
#endif
|
||||||
|
#endif /* not lint */
|
||||||
|
/*
|
||||||
|
#include <sys/cdefs.h>
|
||||||
|
__FBSDID("$FreeBSD: src/bin/sh/arith.y,v 1.19 2004/05/24 10:11:31 stefanf Exp $");
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <limits.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#include "shell.h"
|
||||||
|
#include "arith.h"
|
||||||
|
#include "arith_lex.h"
|
||||||
|
#include "var.h"
|
||||||
|
%}
|
||||||
|
%union {
|
||||||
|
arith_t l_value;
|
||||||
|
char* s_value;
|
||||||
|
}
|
||||||
|
%token <l_value> ARITH_NUM ARITH_LPAREN ARITH_RPAREN
|
||||||
|
%token <s_value> ARITH_VAR
|
||||||
|
|
||||||
|
%type <l_value> expr
|
||||||
|
%right ARITH_ASSIGN
|
||||||
|
%right ARITH_ADDASSIGN ARITH_SUBASSIGN
|
||||||
|
%right ARITH_MULASSIGN ARITH_DIVASSIGN ARITH_REMASSIGN
|
||||||
|
%right ARITH_RSHASSIGN ARITH_LSHASSIGN
|
||||||
|
%right ARITH_BANDASSIGN ARITH_BXORASSIGN ARITH_BORASSIGN
|
||||||
|
%left ARITH_OR
|
||||||
|
%left ARITH_AND
|
||||||
|
%left ARITH_BOR
|
||||||
|
%left ARITH_BXOR
|
||||||
|
%left ARITH_BAND
|
||||||
|
%left ARITH_EQ ARITH_NE
|
||||||
|
%left ARITH_LT ARITH_GT ARITH_GE ARITH_LE
|
||||||
|
%left ARITH_LSHIFT ARITH_RSHIFT
|
||||||
|
%left ARITH_ADD ARITH_SUB
|
||||||
|
%left ARITH_MUL ARITH_DIV ARITH_REM
|
||||||
|
%left ARITH_UNARYMINUS ARITH_UNARYPLUS ARITH_NOT ARITH_BNOT
|
||||||
|
%%
|
||||||
|
|
||||||
|
exp:
|
||||||
|
expr
|
||||||
|
{ return ($1); }
|
||||||
|
;
|
||||||
|
|
||||||
|
expr:
|
||||||
|
ARITH_LPAREN expr ARITH_RPAREN
|
||||||
|
{ $$ = $2; } |
|
||||||
|
expr ARITH_OR expr
|
||||||
|
{ $$ = $1 ? $1 : $3 ? $3 : 0; } |
|
||||||
|
expr ARITH_AND expr
|
||||||
|
{ $$ = $1 ? ( $3 ? $3 : 0 ) : 0; } |
|
||||||
|
expr ARITH_BOR expr
|
||||||
|
{ $$ = $1 | $3; } |
|
||||||
|
expr ARITH_BXOR expr
|
||||||
|
{ $$ = $1 ^ $3; } |
|
||||||
|
expr ARITH_BAND expr
|
||||||
|
{ $$ = $1 & $3; } |
|
||||||
|
expr ARITH_EQ expr
|
||||||
|
{ $$ = $1 == $3; } |
|
||||||
|
expr ARITH_GT expr
|
||||||
|
{ $$ = $1 > $3; } |
|
||||||
|
expr ARITH_GE expr
|
||||||
|
{ $$ = $1 >= $3; } |
|
||||||
|
expr ARITH_LT expr
|
||||||
|
{ $$ = $1 < $3; } |
|
||||||
|
expr ARITH_LE expr
|
||||||
|
{ $$ = $1 <= $3; } |
|
||||||
|
expr ARITH_NE expr
|
||||||
|
{ $$ = $1 != $3; } |
|
||||||
|
expr ARITH_LSHIFT expr
|
||||||
|
{ $$ = $1 << $3; } |
|
||||||
|
expr ARITH_RSHIFT expr
|
||||||
|
{ $$ = $1 >> $3; } |
|
||||||
|
expr ARITH_ADD expr
|
||||||
|
{ $$ = $1 + $3; } |
|
||||||
|
expr ARITH_SUB expr
|
||||||
|
{ $$ = $1 - $3; } |
|
||||||
|
expr ARITH_MUL expr
|
||||||
|
{ $$ = $1 * $3; } |
|
||||||
|
expr ARITH_DIV expr
|
||||||
|
{
|
||||||
|
if ($3 == 0)
|
||||||
|
yyerror("division by zero");
|
||||||
|
$$ = $1 / $3;
|
||||||
|
} |
|
||||||
|
expr ARITH_REM expr
|
||||||
|
{
|
||||||
|
if ($3 == 0)
|
||||||
|
yyerror("division by zero");
|
||||||
|
$$ = $1 % $3;
|
||||||
|
} |
|
||||||
|
ARITH_NOT expr
|
||||||
|
{ $$ = !($2); } |
|
||||||
|
ARITH_BNOT expr
|
||||||
|
{ $$ = ~($2); } |
|
||||||
|
ARITH_SUB expr %prec ARITH_UNARYMINUS
|
||||||
|
{ $$ = -($2); } |
|
||||||
|
ARITH_ADD expr %prec ARITH_UNARYPLUS
|
||||||
|
{ $$ = $2; } |
|
||||||
|
ARITH_NUM |
|
||||||
|
ARITH_VAR
|
||||||
|
{
|
||||||
|
char *p;
|
||||||
|
arith_t arith_val;
|
||||||
|
char *str_val;
|
||||||
|
|
||||||
|
if (lookupvar($1) == NULL)
|
||||||
|
setvarsafe($1, "0", 0);
|
||||||
|
str_val = lookupvar($1);
|
||||||
|
arith_val = strtoarith_t(str_val, &p, 0);
|
||||||
|
/*
|
||||||
|
* Conversion is successful only in case
|
||||||
|
* we've converted _all_ characters.
|
||||||
|
*/
|
||||||
|
if (*p != '\0')
|
||||||
|
yyerror("variable conversion error");
|
||||||
|
$$ = arith_val;
|
||||||
|
} |
|
||||||
|
ARITH_VAR ARITH_ASSIGN expr
|
||||||
|
{
|
||||||
|
if (arith_assign($1, $3) != 0)
|
||||||
|
yyerror("variable assignment error");
|
||||||
|
$$ = $3;
|
||||||
|
} |
|
||||||
|
ARITH_VAR ARITH_ADDASSIGN expr
|
||||||
|
{
|
||||||
|
arith_t value;
|
||||||
|
|
||||||
|
value = atoarith_t(lookupvar($1)) + $3;
|
||||||
|
if (arith_assign($1, value) != 0)
|
||||||
|
yyerror("variable assignment error");
|
||||||
|
$$ = value;
|
||||||
|
} |
|
||||||
|
ARITH_VAR ARITH_SUBASSIGN expr
|
||||||
|
{
|
||||||
|
arith_t value;
|
||||||
|
|
||||||
|
value = atoarith_t(lookupvar($1)) - $3;
|
||||||
|
if (arith_assign($1, value) != 0)
|
||||||
|
yyerror("variable assignment error");
|
||||||
|
$$ = value;
|
||||||
|
} |
|
||||||
|
ARITH_VAR ARITH_MULASSIGN expr
|
||||||
|
{
|
||||||
|
arith_t value;
|
||||||
|
|
||||||
|
value = atoarith_t(lookupvar($1)) * $3;
|
||||||
|
if (arith_assign($1, value) != 0)
|
||||||
|
yyerror("variable assignment error");
|
||||||
|
$$ = value;
|
||||||
|
} |
|
||||||
|
ARITH_VAR ARITH_DIVASSIGN expr
|
||||||
|
{
|
||||||
|
arith_t value;
|
||||||
|
|
||||||
|
if ($3 == 0)
|
||||||
|
yyerror("division by zero");
|
||||||
|
|
||||||
|
value = atoarith_t(lookupvar($1)) / $3;
|
||||||
|
if (arith_assign($1, value) != 0)
|
||||||
|
yyerror("variable assignment error");
|
||||||
|
$$ = value;
|
||||||
|
} |
|
||||||
|
ARITH_VAR ARITH_REMASSIGN expr
|
||||||
|
{
|
||||||
|
arith_t value;
|
||||||
|
|
||||||
|
if ($3 == 0)
|
||||||
|
yyerror("division by zero");
|
||||||
|
|
||||||
|
value = atoarith_t(lookupvar($1)) % $3;
|
||||||
|
if (arith_assign($1, value) != 0)
|
||||||
|
yyerror("variable assignment error");
|
||||||
|
$$ = value;
|
||||||
|
} |
|
||||||
|
ARITH_VAR ARITH_RSHASSIGN expr
|
||||||
|
{
|
||||||
|
arith_t value;
|
||||||
|
|
||||||
|
value = atoarith_t(lookupvar($1)) >> $3;
|
||||||
|
if (arith_assign($1, value) != 0)
|
||||||
|
yyerror("variable assignment error");
|
||||||
|
$$ = value;
|
||||||
|
} |
|
||||||
|
ARITH_VAR ARITH_LSHASSIGN expr
|
||||||
|
{
|
||||||
|
arith_t value;
|
||||||
|
|
||||||
|
value = atoarith_t(lookupvar($1)) << $3;
|
||||||
|
if (arith_assign($1, value) != 0)
|
||||||
|
yyerror("variable assignment error");
|
||||||
|
$$ = value;
|
||||||
|
} |
|
||||||
|
ARITH_VAR ARITH_BANDASSIGN expr
|
||||||
|
{
|
||||||
|
arith_t value;
|
||||||
|
|
||||||
|
value = atoarith_t(lookupvar($1)) & $3;
|
||||||
|
if (arith_assign($1, value) != 0)
|
||||||
|
yyerror("variable assignment error");
|
||||||
|
$$ = value;
|
||||||
|
} |
|
||||||
|
ARITH_VAR ARITH_BXORASSIGN expr
|
||||||
|
{
|
||||||
|
arith_t value;
|
||||||
|
|
||||||
|
value = atoarith_t(lookupvar($1)) ^ $3;
|
||||||
|
if (arith_assign($1, value) != 0)
|
||||||
|
yyerror("variable assignment error");
|
||||||
|
$$ = value;
|
||||||
|
} |
|
||||||
|
ARITH_VAR ARITH_BORASSIGN expr
|
||||||
|
{
|
||||||
|
arith_t value;
|
||||||
|
|
||||||
|
value = atoarith_t(lookupvar($1)) | $3;
|
||||||
|
if (arith_assign($1, value) != 0)
|
||||||
|
yyerror("variable assignment error");
|
||||||
|
$$ = value;
|
||||||
|
} ;
|
||||||
|
%%
|
||||||
|
#include "error.h"
|
||||||
|
#include "output.h"
|
||||||
|
#include "memalloc.h"
|
||||||
|
#include "builtins.h"
|
||||||
|
|
||||||
|
#define lstrlen(var) (3 + (2 + CHAR_BIT * sizeof((var))) / 3)
|
||||||
|
|
||||||
|
char *arith_buf, *arith_startbuf;
|
||||||
|
|
||||||
|
int yylex(void);
|
||||||
|
int yyparse(void);
|
||||||
|
|
||||||
|
int
|
||||||
|
arith_assign(char *name, arith_t value)
|
||||||
|
{
|
||||||
|
char *str;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
str = (char *)ckmalloc(lstrlen(value));
|
||||||
|
sprintf(str, ARITH_FORMAT_STR, value);
|
||||||
|
ret = setvarsafe(name, str, 0);
|
||||||
|
free(str);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
arith(char *s)
|
||||||
|
{
|
||||||
|
long result;
|
||||||
|
|
||||||
|
arith_buf = arith_startbuf = s;
|
||||||
|
|
||||||
|
INTOFF;
|
||||||
|
result = yyparse();
|
||||||
|
arith_lex_reset(); /* Reprime lex. */
|
||||||
|
INTON;
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
yyerror(char *s)
|
||||||
|
{
|
||||||
|
|
||||||
|
yyerrok;
|
||||||
|
yyclearin;
|
||||||
|
arith_lex_reset(); /* Reprime lex. */
|
||||||
|
error("arithmetic expression: %s: \"%s\"", s, arith_startbuf);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The exp(1) builtin.
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
expcmd(int argc, char **argv)
|
||||||
|
{
|
||||||
|
char *p;
|
||||||
|
char *concat;
|
||||||
|
char **ap;
|
||||||
|
long i;
|
||||||
|
|
||||||
|
if (argc > 1) {
|
||||||
|
p = argv[1];
|
||||||
|
if (argc > 2) {
|
||||||
|
/*
|
||||||
|
* Concatenate arguments.
|
||||||
|
*/
|
||||||
|
STARTSTACKSTR(concat);
|
||||||
|
ap = argv + 2;
|
||||||
|
for (;;) {
|
||||||
|
while (*p)
|
||||||
|
STPUTC(*p++, concat);
|
||||||
|
if ((p = *ap++) == NULL)
|
||||||
|
break;
|
||||||
|
STPUTC(' ', concat);
|
||||||
|
}
|
||||||
|
STPUTC('\0', concat);
|
||||||
|
p = grabstackstr(concat);
|
||||||
|
}
|
||||||
|
} else
|
||||||
|
p = "";
|
||||||
|
|
||||||
|
i = arith(p);
|
||||||
|
|
||||||
|
out1fmt("%ld\n", i);
|
||||||
|
return !i;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*************************/
|
||||||
|
#ifdef TEST_ARITH
|
||||||
|
#include <stdio.h>
|
||||||
|
main(int argc, char *argv[])
|
||||||
|
{
|
||||||
|
printf("%d\n", exp(argv[1]));
|
||||||
|
}
|
||||||
|
|
||||||
|
error(char *s)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "exp: %s\n", s);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
* $PchId: arith.y,v 1.6 2006/05/22 12:41:47 philip Exp $
|
||||||
|
*/
|
12
commands/ash/arith_lex.h
Normal file
12
commands/ash/arith_lex.h
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
/*
|
||||||
|
arith_lex.h
|
||||||
|
|
||||||
|
Created: July 1995 by Philip Homburg <philip@cs.vu.nl>
|
||||||
|
*/
|
||||||
|
|
||||||
|
int yylex(void);
|
||||||
|
void arith_lex_reset(void);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* $PchId: arith_lex.h,v 1.1 2001/05/18 19:57:55 philip Exp $
|
||||||
|
*/
|
138
commands/ash/arith_lex.l
Normal file
138
commands/ash/arith_lex.l
Normal file
|
@ -0,0 +1,138 @@
|
||||||
|
%{
|
||||||
|
/*-
|
||||||
|
* Copyright (c) 1993
|
||||||
|
* The Regents of the University of California. All rights reserved.
|
||||||
|
*
|
||||||
|
* This code is derived from software contributed to Berkeley by
|
||||||
|
* Kenneth Almquist.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
* 1. Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* 4. Neither the name of the University nor the names of its contributors
|
||||||
|
* may be used to endorse or promote products derived from this software
|
||||||
|
* without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||||
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||||
|
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
|
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||||
|
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||||
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||||
|
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||||
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||||
|
* SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
#ifndef lint
|
||||||
|
static char sccsid[] = "@(#)arith_lex.l 8.3 (Berkeley) 5/4/95";
|
||||||
|
#endif
|
||||||
|
#endif /* not lint */
|
||||||
|
/*
|
||||||
|
#include <sys/cdefs.h>
|
||||||
|
__FBSDID("$FreeBSD: src/bin/sh/arith_lex.l,v 1.22 2004/04/06 20:06:51 markm Exp $");
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "shell.h"
|
||||||
|
#include "arith_lex.h"
|
||||||
|
#include "arith_y.h"
|
||||||
|
#include "error.h"
|
||||||
|
#include "memalloc.h"
|
||||||
|
#include "var.h"
|
||||||
|
|
||||||
|
extern char *arith_buf, *arith_startbuf;
|
||||||
|
#undef YY_INPUT
|
||||||
|
#define YY_INPUT(buf,result,max) \
|
||||||
|
result = (*buf = *arith_buf++) ? 1 : YY_NULL;
|
||||||
|
#define YY_NO_UNPUT
|
||||||
|
%}
|
||||||
|
|
||||||
|
%%
|
||||||
|
[ \t\n] { ; }
|
||||||
|
|
||||||
|
0x[a-fA-F0-9]+ {
|
||||||
|
yylval.l_value = strtoarith_t(yytext, NULL, 16);
|
||||||
|
return ARITH_NUM;
|
||||||
|
}
|
||||||
|
|
||||||
|
0[0-7]+ {
|
||||||
|
yylval.l_value = strtoarith_t(yytext, NULL, 8);
|
||||||
|
return ARITH_NUM;
|
||||||
|
}
|
||||||
|
|
||||||
|
[0-9]+ {
|
||||||
|
yylval.l_value = strtoarith_t(yytext, NULL, 10);
|
||||||
|
return ARITH_NUM;
|
||||||
|
}
|
||||||
|
|
||||||
|
[A-Za-z][A-Za-z0-9_]* {
|
||||||
|
/*
|
||||||
|
* If variable doesn't exist, we should initialize
|
||||||
|
* it to zero.
|
||||||
|
*/
|
||||||
|
char *temp;
|
||||||
|
if (lookupvar(yytext) == NULL)
|
||||||
|
setvarsafe(yytext, "0", 0);
|
||||||
|
temp = (char *)ckmalloc(strlen(yytext) + 1);
|
||||||
|
yylval.s_value = strcpy(temp, yytext);
|
||||||
|
|
||||||
|
return ARITH_VAR;
|
||||||
|
}
|
||||||
|
|
||||||
|
"(" { return ARITH_LPAREN; }
|
||||||
|
")" { return ARITH_RPAREN; }
|
||||||
|
"||" { return ARITH_OR; }
|
||||||
|
"&&" { return ARITH_AND; }
|
||||||
|
"|" { return ARITH_BOR; }
|
||||||
|
"^" { return ARITH_BXOR; }
|
||||||
|
"&" { return ARITH_BAND; }
|
||||||
|
"==" { return ARITH_EQ; }
|
||||||
|
"!=" { return ARITH_NE; }
|
||||||
|
">" { return ARITH_GT; }
|
||||||
|
">=" { return ARITH_GE; }
|
||||||
|
"<" { return ARITH_LT; }
|
||||||
|
"<=" { return ARITH_LE; }
|
||||||
|
"<<" { return ARITH_LSHIFT; }
|
||||||
|
">>" { return ARITH_RSHIFT; }
|
||||||
|
"*" { return ARITH_MUL; }
|
||||||
|
"/" { return ARITH_DIV; }
|
||||||
|
"%" { return ARITH_REM; }
|
||||||
|
"+" { return ARITH_ADD; }
|
||||||
|
"-" { return ARITH_SUB; }
|
||||||
|
"~" { return ARITH_BNOT; }
|
||||||
|
"!" { return ARITH_NOT; }
|
||||||
|
"=" { return ARITH_ASSIGN; }
|
||||||
|
"+=" { return ARITH_ADDASSIGN; }
|
||||||
|
"-=" { return ARITH_SUBASSIGN; }
|
||||||
|
"*=" { return ARITH_MULASSIGN; }
|
||||||
|
"/=" { return ARITH_DIVASSIGN; }
|
||||||
|
"%=" { return ARITH_REMASSIGN; }
|
||||||
|
">>=" { return ARITH_RSHASSIGN; }
|
||||||
|
"<<=" { return ARITH_LSHASSIGN; }
|
||||||
|
"&=" { return ARITH_BANDASSIGN; }
|
||||||
|
"^=" { return ARITH_BXORASSIGN; }
|
||||||
|
"|=" { return ARITH_BORASSIGN; }
|
||||||
|
. {
|
||||||
|
error("arith: syntax error: \"%s\"\n", arith_startbuf);
|
||||||
|
}
|
||||||
|
%%
|
||||||
|
|
||||||
|
void
|
||||||
|
arith_lex_reset(void)
|
||||||
|
{
|
||||||
|
YY_NEW_FILE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* $PchId: arith_lex.l,v 1.5 2006/04/10 14:35:29 philip Exp $
|
||||||
|
*/
|
|
@ -1,26 +1,78 @@
|
||||||
|
/*-
|
||||||
|
* Copyright (c) 1991, 1993
|
||||||
|
* The Regents of the University of California. All rights reserved.
|
||||||
|
*
|
||||||
|
* This code is derived from software contributed to Berkeley by
|
||||||
|
* Kenneth Almquist.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
* 1. Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* 4. Neither the name of the University nor the names of its contributors
|
||||||
|
* may be used to endorse or promote products derived from this software
|
||||||
|
* without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||||
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||||
|
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
|
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||||
|
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||||
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||||
|
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||||
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||||
|
* SUCH DAMAGE.
|
||||||
|
*
|
||||||
|
* @(#)bltin.h 8.2 (Berkeley) 5/4/95
|
||||||
|
* $FreeBSD: src/bin/sh/bltin/bltin.h,v 1.13 2004/04/06 20:06:53 markm Exp $
|
||||||
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This file is included by programs which are optionally built into the
|
* This file is included by programs which are optionally built into the
|
||||||
* shell. If SHELL is defined, we try to map the standard UNIX library
|
* shell. If SHELL is defined, we try to map the standard UNIX library
|
||||||
* routines to ash routines using defines.
|
* routines to ash routines using defines.
|
||||||
*
|
|
||||||
* Copyright (C) 1989 by Kenneth Almquist. All rights reserved.
|
|
||||||
* This file is part of ash, which is distributed under the terms specified
|
|
||||||
* by the Ash General Public License. See the file named LICENSE.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "../shell.h"
|
#include "../shell.h"
|
||||||
#include "../mystring.h"
|
#include "../mystring.h"
|
||||||
#ifdef SHELL
|
#ifdef SHELL
|
||||||
|
#include "builtins.h"
|
||||||
#include "../output.h"
|
#include "../output.h"
|
||||||
|
#undef stdout
|
||||||
#define stdout out1
|
#define stdout out1
|
||||||
|
#undef stderr
|
||||||
#define stderr out2
|
#define stderr out2
|
||||||
#define printf out1fmt
|
#define printf out1fmt
|
||||||
|
#undef putc
|
||||||
#define putc(c, file) outc(c, file)
|
#define putc(c, file) outc(c, file)
|
||||||
|
#undef putchar
|
||||||
#define putchar(c) out1c(c)
|
#define putchar(c) out1c(c)
|
||||||
#define fprintf outfmt
|
#define fprintf outfmt
|
||||||
#define fputs outstr
|
#define fputs outstr
|
||||||
#define fflush flushout
|
#define fflush flushout
|
||||||
#define INITARGS(argv)
|
#define INITARGS(argv)
|
||||||
|
#define warnx1(a, b, c) { \
|
||||||
|
char buf[64]; \
|
||||||
|
(void)snprintf(buf, sizeof(buf), a); \
|
||||||
|
error("%s", buf); \
|
||||||
|
}
|
||||||
|
#define warnx2(a, b, c) { \
|
||||||
|
char buf[64]; \
|
||||||
|
(void)snprintf(buf, sizeof(buf), a, b); \
|
||||||
|
error("%s", buf); \
|
||||||
|
}
|
||||||
|
#define warnx3(a, b, c) { \
|
||||||
|
char buf[64]; \
|
||||||
|
(void)snprintf(buf, sizeof(buf), a, b, c); \
|
||||||
|
error("%s", buf); \
|
||||||
|
}
|
||||||
|
|
||||||
#else
|
#else
|
||||||
#undef NULL
|
#undef NULL
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
@ -28,13 +80,12 @@
|
||||||
#define INITARGS(argv) if ((commandname = argv[0]) == NULL) {fputs("Argc is zero\n", stderr); exit(2);} else
|
#define INITARGS(argv) if ((commandname = argv[0]) == NULL) {fputs("Argc is zero\n", stderr); exit(2);} else
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef __STDC__
|
|
||||||
pointer stalloc(int);
|
pointer stalloc(int);
|
||||||
void error(char *, ...);
|
void error(const char *, ...);
|
||||||
#else
|
|
||||||
pointer stalloc();
|
|
||||||
void error();
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
extern char *commandname;
|
extern char *commandname;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* $PchId: bltin.h,v 1.4 2006/03/29 11:39:00 philip Exp $
|
||||||
|
*/
|
||||||
|
|
|
@ -1,22 +1,66 @@
|
||||||
/*
|
/*-
|
||||||
* Echo command.
|
* Copyright (c) 1991, 1993
|
||||||
|
* The Regents of the University of California. All rights reserved.
|
||||||
*
|
*
|
||||||
* Copyright (C) 1989 by Kenneth Almquist. All rights reserved.
|
* This code is derived from software contributed to Berkeley by
|
||||||
* This file is part of ash, which is distributed under the terms specified
|
* Kenneth Almquist.
|
||||||
* by the Ash General Public License. See the file named LICENSE.
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
* 1. Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* 4. Neither the name of the University nor the names of its contributors
|
||||||
|
* may be used to endorse or promote products derived from this software
|
||||||
|
* without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||||
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||||
|
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
|
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||||
|
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||||
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||||
|
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||||
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||||
|
* SUCH DAMAGE.
|
||||||
|
*
|
||||||
|
* @(#)echo.c 8.2 (Berkeley) 5/4/95
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define main echocmd
|
/*
|
||||||
|
#include <sys/cdefs.h>
|
||||||
|
__FBSDID("$FreeBSD: src/bin/sh/bltin/echo.c,v 1.14 2004/04/06 20:06:53 markm Exp $");
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Echo command.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifdef __minix
|
||||||
|
#define MINIX
|
||||||
|
#endif
|
||||||
|
|
||||||
#include "bltin.h"
|
#include "bltin.h"
|
||||||
|
|
||||||
|
#ifndef MINIX
|
||||||
|
/* #define eflag 1 */
|
||||||
|
#else
|
||||||
#undef eflag
|
#undef eflag
|
||||||
|
#endif
|
||||||
|
|
||||||
|
int
|
||||||
main(argc, argv) char **argv; {
|
echocmd(argc, argv)
|
||||||
register char **ap;
|
int argc;
|
||||||
register char *p;
|
char **argv;
|
||||||
register char c;
|
{
|
||||||
|
char **ap;
|
||||||
|
char *p;
|
||||||
|
char c;
|
||||||
int count;
|
int count;
|
||||||
int nflag = 0;
|
int nflag = 0;
|
||||||
#ifndef eflag
|
#ifndef eflag
|
||||||
|
@ -27,9 +71,11 @@ main(argc, argv) char **argv; {
|
||||||
if (argc)
|
if (argc)
|
||||||
ap++;
|
ap++;
|
||||||
if ((p = *ap) != NULL) {
|
if ((p = *ap) != NULL) {
|
||||||
|
#ifdef MINIX
|
||||||
if (equal(p, "--")) {
|
if (equal(p, "--")) {
|
||||||
ap++;
|
ap++;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
if (equal(p, "-n")) {
|
if (equal(p, "-n")) {
|
||||||
nflag++;
|
nflag++;
|
||||||
ap++;
|
ap++;
|
||||||
|
@ -44,8 +90,10 @@ main(argc, argv) char **argv; {
|
||||||
while ((c = *p++) != '\0') {
|
while ((c = *p++) != '\0') {
|
||||||
if (c == '\\' && eflag) {
|
if (c == '\\' && eflag) {
|
||||||
switch (*p++) {
|
switch (*p++) {
|
||||||
|
case 'a': c = '\a'; break;
|
||||||
case 'b': c = '\b'; break;
|
case 'b': c = '\b'; break;
|
||||||
case 'c': return 0; /* exit */
|
case 'c': return 0; /* exit */
|
||||||
|
case 'e': c = '\033'; break;
|
||||||
case 'f': c = '\f'; break;
|
case 'f': c = '\f'; break;
|
||||||
case 'n': c = '\n'; break;
|
case 'n': c = '\n'; break;
|
||||||
case 'r': c = '\r'; break;
|
case 'r': c = '\r'; break;
|
||||||
|
@ -72,3 +120,7 @@ main(argc, argv) char **argv; {
|
||||||
putchar('\n');
|
putchar('\n');
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* $PchId: echo.c,v 1.5 2006/05/23 12:05:56 philip Exp $
|
||||||
|
*/
|
||||||
|
|
|
@ -7,17 +7,14 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
#define main exprcmd
|
|
||||||
|
|
||||||
#include "bltin.h"
|
#include "bltin.h"
|
||||||
#include "operators.h"
|
#include "operators.h"
|
||||||
|
#include <regex.h>
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
#ifndef S_ISLNK
|
|
||||||
#define lstat stat
|
|
||||||
#define S_ISLNK(mode) (0)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define STACKSIZE 12
|
#define STACKSIZE 12
|
||||||
#define NESTINCR 16
|
#define NESTINCR 16
|
||||||
|
@ -50,7 +47,6 @@ struct operator {
|
||||||
|
|
||||||
|
|
||||||
struct filestat {
|
struct filestat {
|
||||||
int op; /* OP_FILE or OP_LFILE */
|
|
||||||
char *name; /* name of file */
|
char *name; /* name of file */
|
||||||
int rcode; /* return code from stat */
|
int rcode; /* return code from stat */
|
||||||
struct stat stat; /* status info on file */
|
struct stat stat; /* status info on file */
|
||||||
|
@ -63,24 +59,18 @@ extern short number_parens; /* number of \( \) pairs */
|
||||||
|
|
||||||
|
|
||||||
#ifdef __STDC__
|
#ifdef __STDC__
|
||||||
int expr_is_false(struct value *);
|
static int expr_is_false(struct value *);
|
||||||
void expr_operator(int, struct value *, struct filestat *);
|
static void expr_operator(int, struct value *, struct filestat *);
|
||||||
int lookup_op(char *, char *const*);
|
static int lookup_op(char *, char *const*);
|
||||||
char *re_compile(char *); /* defined in regexp.c */
|
|
||||||
int re_match(char *, char *); /* defined in regexp.c */
|
|
||||||
long atol(const char *);
|
|
||||||
#else
|
#else
|
||||||
int expr_is_false();
|
static int expr_is_false();
|
||||||
void expr_operator();
|
static void expr_operator();
|
||||||
int lookup_op();
|
static int lookup_op();
|
||||||
char *re_compile(); /* defined in regexp.c */
|
|
||||||
int re_match(); /* defined in regexp.c */
|
|
||||||
long atol();
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
main(argc, argv) char **argv; {
|
exprcmd(argc, argv) char **argv; {
|
||||||
char **ap;
|
char **ap;
|
||||||
char *opname;
|
char *opname;
|
||||||
char c;
|
char c;
|
||||||
|
@ -146,6 +136,13 @@ overflow: error("Expression too complex");
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
if (opname[0] == '\'') {
|
||||||
|
for (p = opname ; *++p != '\0' ; );
|
||||||
|
if (--p > opname && *p == '\'') {
|
||||||
|
*p = '\0';
|
||||||
|
opname++;
|
||||||
|
}
|
||||||
|
}
|
||||||
valsp->type = STRING;
|
valsp->type = STRING;
|
||||||
valsp->u.string = opname;
|
valsp->u.string = opname;
|
||||||
valsp++;
|
valsp++;
|
||||||
|
@ -193,19 +190,11 @@ overflow: error("Expression too complex");
|
||||||
valsp->u.string = "";
|
valsp->u.string = "";
|
||||||
}
|
}
|
||||||
valsp->type = STRING;
|
valsp->type = STRING;
|
||||||
if (c >= OP_FILE
|
if (c == OP_FILE
|
||||||
&& (fs.op != c
|
&& (fs.name == NULL
|
||||||
|| fs.name == NULL
|
|
||||||
|| ! equal(fs.name, valsp->u.string))) {
|
|| ! equal(fs.name, valsp->u.string))) {
|
||||||
fs.op = c;
|
|
||||||
fs.name = valsp->u.string;
|
fs.name = valsp->u.string;
|
||||||
if (c == OP_FILE) {
|
fs.rcode = stat(valsp->u.string, &fs.stat);
|
||||||
fs.rcode = stat(valsp->u.string,
|
|
||||||
&fs.stat);
|
|
||||||
} else {
|
|
||||||
fs.rcode = lstat(valsp->u.string,
|
|
||||||
&fs.stat);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (binary < FIRST_BINARY_OP)
|
if (binary < FIRST_BINARY_OP)
|
||||||
|
@ -250,7 +239,7 @@ done:
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int
|
static int
|
||||||
expr_is_false(val)
|
expr_is_false(val)
|
||||||
struct value *val;
|
struct value *val;
|
||||||
{
|
{
|
||||||
|
@ -274,14 +263,16 @@ expr_is_false(val)
|
||||||
* to stat, to avoid repeated stat calls on the same file.
|
* to stat, to avoid repeated stat calls on the same file.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void
|
static void
|
||||||
expr_operator(op, sp, fs)
|
expr_operator(op, sp, fs)
|
||||||
int op;
|
int op;
|
||||||
struct value *sp;
|
struct value *sp;
|
||||||
struct filestat *fs;
|
struct filestat *fs;
|
||||||
{
|
{
|
||||||
int i;
|
int i, r;
|
||||||
struct stat st1, st2;
|
struct stat st1, st2;
|
||||||
|
regex_t pat;
|
||||||
|
regmatch_t rm[2];
|
||||||
|
|
||||||
switch (op) {
|
switch (op) {
|
||||||
case NOT:
|
case NOT:
|
||||||
|
@ -343,16 +334,16 @@ filebit:
|
||||||
if (fs->stat.st_mode & i && fs->rcode >= 0)
|
if (fs->stat.st_mode & i && fs->rcode >= 0)
|
||||||
goto true;
|
goto true;
|
||||||
goto false;
|
goto false;
|
||||||
|
case ISSLINK:
|
||||||
|
if (lstat(fs->name, &st1) == -1)
|
||||||
|
goto false;
|
||||||
|
if (S_ISLNK(st1.st_mode))
|
||||||
|
goto true;
|
||||||
|
goto false;
|
||||||
case ISSIZE:
|
case ISSIZE:
|
||||||
sp->u.num = fs->rcode >= 0? fs->stat.st_size : 0L;
|
sp->u.num = fs->rcode >= 0? fs->stat.st_size : 0L;
|
||||||
sp->type = INTEGER;
|
sp->type = INTEGER;
|
||||||
break;
|
break;
|
||||||
case ISLINK1:
|
|
||||||
case ISLINK2:
|
|
||||||
if (S_ISLNK(fs->stat.st_mode) && fs->rcode >= 0)
|
|
||||||
goto true;
|
|
||||||
fs->op = OP_FILE; /* not a symlink, so expect a -d or so next */
|
|
||||||
goto false;
|
|
||||||
case NEWER:
|
case NEWER:
|
||||||
if (stat(sp->u.string, &st1) != 0) {
|
if (stat(sp->u.string, &st1) != 0) {
|
||||||
sp->u.num = 0;
|
sp->u.num = 0;
|
||||||
|
@ -439,19 +430,21 @@ filebit:
|
||||||
break;
|
break;
|
||||||
case MATCHPAT:
|
case MATCHPAT:
|
||||||
{
|
{
|
||||||
char *pat;
|
r = regcomp(&pat, (sp + 1)->u.string, 0);
|
||||||
|
if (r)
|
||||||
pat = re_compile((sp + 1)->u.string);
|
error("Bad regular expression");
|
||||||
if (re_match(pat, sp->u.string)) {
|
if (regexec(&pat, sp->u.string, 2, rm, 0) == 0 &&
|
||||||
if (number_parens > 0) {
|
rm[0].rm_so == 0)
|
||||||
sp->u.string = match_begin[1];
|
{
|
||||||
sp->u.string[match_length[1]] = '\0';
|
if (pat.re_nsub > 0) {
|
||||||
|
sp->u.string[rm[1].rm_eo] = '\0';
|
||||||
|
sp->u.string = sp->u.string+rm[1].rm_so;
|
||||||
} else {
|
} else {
|
||||||
sp->u.num = match_length[0];
|
sp->u.num = rm[0].rm_eo;
|
||||||
sp->type = INTEGER;
|
sp->type = INTEGER;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (number_parens > 0) {
|
if (pat.re_nsub > 0) {
|
||||||
sp->u.string[0] = '\0';
|
sp->u.string[0] = '\0';
|
||||||
} else {
|
} else {
|
||||||
sp->u.num = 0;
|
sp->u.num = 0;
|
||||||
|
@ -464,7 +457,7 @@ filebit:
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int
|
static int
|
||||||
lookup_op(name, table)
|
lookup_op(name, table)
|
||||||
char *name;
|
char *name;
|
||||||
char *const*table;
|
char *const*table;
|
||||||
|
|
|
@ -5,21 +5,28 @@
|
||||||
|
|
||||||
# All calls to awk removed, because Minix bawk is deficient. (kjb)
|
# All calls to awk removed, because Minix bawk is deficient. (kjb)
|
||||||
|
|
||||||
|
if [ $# -ne 2 ]
|
||||||
|
then
|
||||||
|
echo "Usage: $0 <unary_op> <binary_op>" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
unary_op="$1"
|
||||||
|
binary_op="$2"
|
||||||
|
|
||||||
exec > operators.h
|
exec > operators.h
|
||||||
i=0
|
i=0
|
||||||
sed -e '/^[^#]/!d' unary_op binary_op | while read line
|
sed -e '/^[^#]/!d' "$unary_op" "$binary_op" | while read line
|
||||||
do
|
do
|
||||||
set -$- $line
|
set -$- $line
|
||||||
echo "#define $1 $i"
|
echo "#define $1 $i"
|
||||||
i=`expr $i + 1`
|
i=`expr $i + 1`
|
||||||
done
|
done
|
||||||
echo
|
echo
|
||||||
echo "#define FIRST_BINARY_OP" `sed -e '/^[^#]/!d' unary_op | wc -l`
|
echo "#define FIRST_BINARY_OP" `sed -e '/^[^#]/!d' "$unary_op" | wc -l`
|
||||||
echo '
|
echo '
|
||||||
#define OP_INT 1 /* arguments to operator are integer */
|
#define OP_INT 1 /* arguments to operator are integer */
|
||||||
#define OP_STRING 2 /* arguments to operator are string */
|
#define OP_STRING 2 /* arguments to operator are string */
|
||||||
#define OP_FILE 3 /* argument is a file name */
|
#define OP_FILE 3 /* argument is a file name */
|
||||||
#define OP_LFILE 4 /* argument is a file name of a symlink? */
|
|
||||||
|
|
||||||
extern char *const unary_op[];
|
extern char *const unary_op[];
|
||||||
extern char *const binary_op[];
|
extern char *const binary_op[];
|
||||||
|
@ -31,14 +38,15 @@ echo '/*
|
||||||
* Operators used in the expr/test command.
|
* Operators used in the expr/test command.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "../shell.h"
|
#include <stddef.h>
|
||||||
|
#include "shell.h"
|
||||||
#include "operators.h"
|
#include "operators.h"
|
||||||
|
|
||||||
char *const unary_op[] = {'
|
char *const unary_op[] = {'
|
||||||
sed -e '/^[^#]/!d
|
sed -e '/^[^#]/!d
|
||||||
s/[ ][ ]*/ /g
|
s/[ ][ ]*/ /g
|
||||||
s/^[^ ][^ ]* \([^ ][^ ]*\).*/ "\1",/
|
s/^[^ ][^ ]* \([^ ][^ ]*\).*/ "\1",/
|
||||||
' unary_op
|
' "$unary_op"
|
||||||
echo ' NULL
|
echo ' NULL
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -46,7 +54,7 @@ char *const binary_op[] = {'
|
||||||
sed -e '/^[^#]/!d
|
sed -e '/^[^#]/!d
|
||||||
s/[ ][ ]*/ /g
|
s/[ ][ ]*/ /g
|
||||||
s/^[^ ][^ ]* \([^ ][^ ]*\).*/ "\1",/
|
s/^[^ ][^ ]* \([^ ][^ ]*\).*/ "\1",/
|
||||||
' binary_op
|
' "$binary_op"
|
||||||
echo ' NULL
|
echo ' NULL
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -54,7 +62,7 @@ const char op_priority[] = {'
|
||||||
sed -e '/^[^#]/!d
|
sed -e '/^[^#]/!d
|
||||||
s/[ ][ ]*/ /g
|
s/[ ][ ]*/ /g
|
||||||
s/^[^ ][^ ]* [^ ][^ ]* \([^ ][^ ]*\).*/ \1,/
|
s/^[^ ][^ ]* [^ ][^ ]* \([^ ][^ ]*\).*/ \1,/
|
||||||
' unary_op binary_op
|
' "$unary_op" "$binary_op"
|
||||||
echo '};
|
echo '};
|
||||||
|
|
||||||
const char op_argflag[] = {'
|
const char op_argflag[] = {'
|
||||||
|
@ -62,5 +70,5 @@ sed -e '/^[^#]/!d
|
||||||
s/[ ][ ]*/ /g
|
s/[ ][ ]*/ /g
|
||||||
s/^[^ ][^ ]* [^ ][^ ]* [^ ][^ ]*$/& 0/
|
s/^[^ ][^ ]* [^ ][^ ]* [^ ][^ ]*$/& 0/
|
||||||
s/^[^ ][^ ]* [^ ][^ ]* [^ ][^ ]* \([^ ][^ ]*\)/ \1,/
|
s/^[^ ][^ ]* [^ ][^ ]* [^ ][^ ]* \([^ ][^ ]*\)/ \1,/
|
||||||
' unary_op binary_op
|
' "$unary_op" "$binary_op"
|
||||||
echo '};'
|
echo '};'
|
||||||
|
|
8
commands/ash/bltin/myregexp.h
Normal file
8
commands/ash/bltin/myregexp.h
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
/*
|
||||||
|
myregexp.h
|
||||||
|
|
||||||
|
Created: July 1995 by Philip Homburg <philip@cs.vu.nl>
|
||||||
|
*/
|
||||||
|
|
||||||
|
char *re_compile(char *pattern);
|
||||||
|
int re_match(char *pattern, char *string);
|
|
@ -8,7 +8,9 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "bltin.h"
|
#include "bltin.h"
|
||||||
|
#include "myregexp.h"
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
#define RE_END 0 /* end of regular expression */
|
#define RE_END 0 /* end of regular expression */
|
||||||
#define RE_LITERAL 1 /* normal character follows */
|
#define RE_LITERAL 1 /* normal character follows */
|
||||||
|
@ -27,7 +29,7 @@
|
||||||
char *match_begin[10];
|
char *match_begin[10];
|
||||||
short match_length[10];
|
short match_length[10];
|
||||||
short number_parens;
|
short number_parens;
|
||||||
static int match();
|
static int match(char *pattern, char *string);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -48,7 +50,6 @@ re_compile(pattern)
|
||||||
char stack[10];
|
char stack[10];
|
||||||
int paren_num;
|
int paren_num;
|
||||||
int i;
|
int i;
|
||||||
char *malloc();
|
|
||||||
|
|
||||||
p = pattern;
|
p = pattern;
|
||||||
if (*p == '^')
|
if (*p == '^')
|
||||||
|
@ -176,6 +177,7 @@ out:
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
int
|
||||||
re_match(pattern, string)
|
re_match(pattern, string)
|
||||||
char *pattern;
|
char *pattern;
|
||||||
char *string;
|
char *string;
|
||||||
|
@ -246,7 +248,7 @@ ccl:
|
||||||
p++;
|
p++;
|
||||||
}
|
}
|
||||||
p++;
|
p++;
|
||||||
if (found == negate || c == 0)
|
if (found == negate)
|
||||||
goto bad;
|
goto bad;
|
||||||
break;
|
break;
|
||||||
case RE_LP:
|
case RE_LP:
|
||||||
|
|
|
@ -16,9 +16,8 @@ ISFIFO -p 12 OP_FILE
|
||||||
ISSETUID -u 12 OP_FILE
|
ISSETUID -u 12 OP_FILE
|
||||||
ISSETGID -g 12 OP_FILE
|
ISSETGID -g 12 OP_FILE
|
||||||
ISSTICKY -k 12 OP_FILE
|
ISSTICKY -k 12 OP_FILE
|
||||||
|
ISSLINK -h 12 OP_FILE
|
||||||
ISSIZE -s 12 OP_FILE
|
ISSIZE -s 12 OP_FILE
|
||||||
ISLINK1 -h 12 OP_LFILE
|
|
||||||
ISLINK2 -L 12 OP_LFILE
|
|
||||||
ISTTY -t 12 OP_INT
|
ISTTY -t 12 OP_INT
|
||||||
NULSTR -z 12 OP_STRING
|
NULSTR -z 12 OP_STRING
|
||||||
STRLEN -n 12 OP_STRING
|
STRLEN -n 12 OP_STRING
|
||||||
|
|
|
@ -1,3 +0,0 @@
|
||||||
#!/bin/sh
|
|
||||||
make clean
|
|
||||||
make && make install
|
|
21
commands/ash/builtins.table → commands/ash/builtins
Executable file → Normal file
21
commands/ash/builtins.table → commands/ash/builtins
Executable file → Normal file
|
@ -1,7 +1,7 @@
|
||||||
#!/bin/sh -
|
#!/bin/sh -
|
||||||
#
|
#
|
||||||
# Copyright (c) 1991 The Regents of the University of California.
|
# Copyright (c) 1991, 1993
|
||||||
# All rights reserved.
|
# The Regents of the University of California. All rights reserved.
|
||||||
#
|
#
|
||||||
# This code is derived from software contributed to Berkeley by
|
# This code is derived from software contributed to Berkeley by
|
||||||
# Kenneth Almquist.
|
# Kenneth Almquist.
|
||||||
|
@ -34,19 +34,21 @@
|
||||||
# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||||
# SUCH DAMAGE.
|
# SUCH DAMAGE.
|
||||||
#
|
#
|
||||||
# @(#)builtins 5.1 (Berkeley) 3/7/91
|
# @(#)builtins 8.1 (Berkeley) 5/31/93
|
||||||
|
|
||||||
#
|
#
|
||||||
# This file lists all the builtin commands. The first column is the name
|
# This file lists all the builtin commands. The first column is the name
|
||||||
# of a C routine. The -j flag, if present, specifies that this command
|
# of a C routine. The -j flag, if present, specifies that this command
|
||||||
# is to be excluded from systems without job control. The rest of the line
|
# is to be excluded from systems without job control. The rest of the line
|
||||||
# specifies the command name or names used to run the command. The entry
|
# specifies the command name or names used to run the command. The entry
|
||||||
# for nullcmd, which is run when the user does not specify a command, must
|
# for bltincmd, which is run when the user does not specify a command, must
|
||||||
# come first.
|
# come first.
|
||||||
#
|
#
|
||||||
# Copyright (C) 1989 by Kenneth Almquist. All rights reserved.
|
# Copyright (C) 1989 by Kenneth Almquist. All rights reserved.
|
||||||
# This file is part of ash, which is distributed under the terms specified
|
# This file is part of ash, which is distributed under the terms specified
|
||||||
# by the Ash General Public License. See the file named LICENSE.
|
# by the Ash General Public License. See the file named LICENSE.
|
||||||
|
#
|
||||||
|
# NOTE: bltincmd must come first!
|
||||||
|
|
||||||
bltincmd command
|
bltincmd command
|
||||||
#alloccmd alloc
|
#alloccmd alloc
|
||||||
|
@ -59,17 +61,19 @@ echocmd echo
|
||||||
evalcmd eval
|
evalcmd eval
|
||||||
execcmd exec
|
execcmd exec
|
||||||
exitcmd exit
|
exitcmd exit
|
||||||
|
expcmd exp let
|
||||||
exportcmd export readonly
|
exportcmd export readonly
|
||||||
exprcmd expr test [
|
#exprcmd expr test [
|
||||||
|
histcmd fc
|
||||||
fgcmd -j fg
|
fgcmd -j fg
|
||||||
getoptscmd getopts
|
getoptscmd getopts
|
||||||
hashcmd hash
|
hashcmd hash
|
||||||
jobidcmd jobid
|
jobidcmd jobid
|
||||||
jobscmd jobs
|
jobscmd jobs
|
||||||
#lccmd lc
|
|
||||||
#linecmd line
|
#linecmd line
|
||||||
localcmd local
|
localcmd local
|
||||||
#nlechocmd nlecho
|
#nlechocmd nlecho
|
||||||
|
printfcmd printf
|
||||||
pwdcmd pwd
|
pwdcmd pwd
|
||||||
readcmd read
|
readcmd read
|
||||||
returncmd return
|
returncmd return
|
||||||
|
@ -77,7 +81,10 @@ setcmd set
|
||||||
setvarcmd setvar
|
setvarcmd setvar
|
||||||
shiftcmd shift
|
shiftcmd shift
|
||||||
trapcmd trap
|
trapcmd trap
|
||||||
truecmd : true false
|
truecmd : true
|
||||||
umaskcmd umask
|
umaskcmd umask
|
||||||
|
unaliascmd unalias
|
||||||
unsetcmd unset
|
unsetcmd unset
|
||||||
waitcmd wait
|
waitcmd wait
|
||||||
|
#foocmd foo
|
||||||
|
aliascmd alias
|
94
commands/ash/builtins.def
Normal file
94
commands/ash/builtins.def
Normal file
|
@ -0,0 +1,94 @@
|
||||||
|
#!/bin/sh -
|
||||||
|
#
|
||||||
|
# Copyright (c) 1991, 1993
|
||||||
|
# The Regents of the University of California. All rights reserved.
|
||||||
|
#
|
||||||
|
# This code is derived from software contributed to Berkeley by
|
||||||
|
# Kenneth Almquist.
|
||||||
|
#
|
||||||
|
# Redistribution and use in source and binary forms, with or without
|
||||||
|
# modification, are permitted provided that the following conditions
|
||||||
|
# are met:
|
||||||
|
# 1. Redistributions of source code must retain the above copyright
|
||||||
|
# notice, this list of conditions and the following disclaimer.
|
||||||
|
# 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
# notice, this list of conditions and the following disclaimer in the
|
||||||
|
# documentation and/or other materials provided with the distribution.
|
||||||
|
# 4. Neither the name of the University nor the names of its contributors
|
||||||
|
# may be used to endorse or promote products derived from this software
|
||||||
|
# without specific prior written permission.
|
||||||
|
#
|
||||||
|
# THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||||
|
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
# ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||||
|
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
|
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||||
|
# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||||
|
# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||||
|
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||||
|
# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||||
|
# SUCH DAMAGE.
|
||||||
|
#
|
||||||
|
# @(#)builtins.def 8.4 (Berkeley) 5/4/95
|
||||||
|
# $FreeBSD: src/bin/sh/builtins.def,v 1.14 2004/04/06 20:06:51 markm Exp $
|
||||||
|
|
||||||
|
#
|
||||||
|
# This file lists all the builtin commands. The first column is the name
|
||||||
|
# of a C routine. The -j flag, if present, specifies that this command
|
||||||
|
# is to be excluded from systems without job control, and the -h flag,
|
||||||
|
# if present specifies that this command is to be excluded from systems
|
||||||
|
# based on the NO_HISTORY compile-time symbol. The rest of the line
|
||||||
|
# specifies the command name or names used to run the command. The entry
|
||||||
|
# for bltincmd, which is run when the user does not specify a command, must
|
||||||
|
# come first.
|
||||||
|
#
|
||||||
|
# NOTE: bltincmd must come first!
|
||||||
|
|
||||||
|
bltincmd builtin
|
||||||
|
commandcmd command
|
||||||
|
#alloccmd alloc
|
||||||
|
bgcmd -j bg
|
||||||
|
breakcmd break continue
|
||||||
|
#catfcmd catf
|
||||||
|
cdcmd cd chdir
|
||||||
|
dotcmd .
|
||||||
|
echocmd echo
|
||||||
|
evalcmd eval
|
||||||
|
execcmd exec
|
||||||
|
exitcmd exit
|
||||||
|
expcmd exp let
|
||||||
|
exportcmd export readonly
|
||||||
|
exprcmd expr test [
|
||||||
|
falsecmd false
|
||||||
|
histcmd -h fc
|
||||||
|
fgcmd -j fg
|
||||||
|
getoptscmd getopts
|
||||||
|
hashcmd hash
|
||||||
|
jobidcmd jobid
|
||||||
|
jobscmd jobs
|
||||||
|
#linecmd line
|
||||||
|
localcmd local
|
||||||
|
#nlechocmd nlecho
|
||||||
|
#printfcmd printf
|
||||||
|
pwdcmd pwd
|
||||||
|
readcmd read
|
||||||
|
returncmd return
|
||||||
|
setcmd set
|
||||||
|
setvarcmd setvar
|
||||||
|
shiftcmd shift
|
||||||
|
trapcmd trap
|
||||||
|
truecmd : true
|
||||||
|
typecmd type
|
||||||
|
umaskcmd umask
|
||||||
|
unaliascmd unalias
|
||||||
|
unsetcmd unset
|
||||||
|
waitcmd wait
|
||||||
|
#foocmd foo
|
||||||
|
aliascmd alias
|
||||||
|
ulimitcmd ulimit
|
||||||
|
bindcmd bind
|
||||||
|
wordexpcmd wordexp
|
||||||
|
|
||||||
|
#
|
||||||
|
# $PchId: builtins.def,v 1.5 2006/03/31 10:50:57 philip Exp $
|
|
@ -1,6 +1,6 @@
|
||||||
/*-
|
/*-
|
||||||
* Copyright (c) 1991 The Regents of the University of California.
|
* Copyright (c) 1991, 1993
|
||||||
* All rights reserved.
|
* The Regents of the University of California. All rights reserved.
|
||||||
*
|
*
|
||||||
* This code is derived from software contributed to Berkeley by
|
* This code is derived from software contributed to Berkeley by
|
||||||
* Kenneth Almquist.
|
* Kenneth Almquist.
|
||||||
|
@ -13,10 +13,6 @@
|
||||||
* 2. Redistributions in binary form must reproduce the above copyright
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
* notice, this list of conditions and the following disclaimer in the
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
* documentation and/or other materials provided with the distribution.
|
* documentation and/or other materials provided with the distribution.
|
||||||
* 3. All advertising materials mentioning features or use of this software
|
|
||||||
* must display the following acknowledgement:
|
|
||||||
* This product includes software developed by the University of
|
|
||||||
* California, Berkeley and its contributors.
|
|
||||||
* 4. Neither the name of the University nor the names of its contributors
|
* 4. Neither the name of the University nor the names of its contributors
|
||||||
* may be used to endorse or promote products derived from this software
|
* may be used to endorse or promote products derived from this software
|
||||||
* without specific prior written permission.
|
* without specific prior written permission.
|
||||||
|
@ -35,8 +31,22 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef lint
|
#ifndef lint
|
||||||
static char sccsid[] = "@(#)cd.c 5.2 (Berkeley) 3/13/91";
|
#if 0
|
||||||
|
static char sccsid[] = "@(#)cd.c 8.2 (Berkeley) 5/4/95";
|
||||||
|
#endif
|
||||||
#endif /* not lint */
|
#endif /* not lint */
|
||||||
|
/*
|
||||||
|
#include <sys/cdefs.h>
|
||||||
|
__FBSDID("$FreeBSD: src/bin/sh/cd.c,v 1.34 2004/04/06 20:06:51 markm Exp $");
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <limits.h>
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The cd and pwd commands.
|
* The cd and pwd commands.
|
||||||
|
@ -50,115 +60,124 @@ static char sccsid[] = "@(#)cd.c 5.2 (Berkeley) 3/13/91";
|
||||||
#include "output.h"
|
#include "output.h"
|
||||||
#include "memalloc.h"
|
#include "memalloc.h"
|
||||||
#include "error.h"
|
#include "error.h"
|
||||||
|
#include "exec.h"
|
||||||
|
#include "redir.h"
|
||||||
#include "mystring.h"
|
#include "mystring.h"
|
||||||
#include <sys/types.h>
|
#include "builtins.h"
|
||||||
#include <sys/stat.h>
|
#include "show.h"
|
||||||
#include <errno.h>
|
#include "cd.h"
|
||||||
|
|
||||||
|
STATIC int cdlogical(char *);
|
||||||
#ifdef __STDC__
|
STATIC int cdphysical(char *);
|
||||||
STATIC int docd(char *, int, int);
|
STATIC int docd(char *, int, int);
|
||||||
STATIC void updatepwd(char *);
|
|
||||||
STATIC void getpwd(void);
|
|
||||||
STATIC char *getcomponent(void);
|
STATIC char *getcomponent(void);
|
||||||
#else
|
STATIC int updatepwd(char *);
|
||||||
STATIC int docd();
|
|
||||||
STATIC void updatepwd();
|
|
||||||
STATIC void getpwd();
|
|
||||||
STATIC char *getcomponent();
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
STATIC char *curdir = NULL; /* current working directory */
|
||||||
char *curdir; /* current working directory */
|
STATIC char *prevdir; /* previous working directory */
|
||||||
STATIC char *cdcomppath;
|
STATIC char *cdcomppath;
|
||||||
|
|
||||||
#if UDIR || TILDE
|
|
||||||
extern int didudir; /* set if /u/logname or ~logname expanded */
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
int
|
int
|
||||||
cdcmd(argc, argv) char **argv; {
|
cdcmd(int argc, char **argv)
|
||||||
|
{
|
||||||
char *dest;
|
char *dest;
|
||||||
char *path;
|
char *path;
|
||||||
char *p;
|
char *p;
|
||||||
struct stat statb;
|
struct stat statb;
|
||||||
char *padvance();
|
int ch, phys, print = 0;
|
||||||
int tohome= 0;
|
|
||||||
|
|
||||||
nextopt(nullstr);
|
optreset = 1; optind = 1; opterr = 0; /* initialize getopt */
|
||||||
if ((dest = *argptr) == NULL) {
|
phys = Pflag;
|
||||||
if ((dest = bltinlookup("HOME", 1)) == NULL)
|
while ((ch = getopt(argc, argv, "LP")) != -1) {
|
||||||
|
switch (ch) {
|
||||||
|
case 'L':
|
||||||
|
phys = 0;
|
||||||
|
break;
|
||||||
|
case 'P':
|
||||||
|
phys = 1;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
error("unknown option: -%c", optopt);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
argc -= optind;
|
||||||
|
argv += optind;
|
||||||
|
|
||||||
|
if (argc > 1)
|
||||||
|
error("too many arguments");
|
||||||
|
|
||||||
|
if ((dest = *argv) == NULL && (dest = bltinlookup("HOME", 1)) == NULL)
|
||||||
error("HOME not set");
|
error("HOME not set");
|
||||||
tohome = 1;
|
if (*dest == '\0')
|
||||||
|
dest = ".";
|
||||||
|
if (dest[0] == '-' && dest[1] == '\0') {
|
||||||
|
dest = prevdir ? prevdir : curdir;
|
||||||
|
if (dest)
|
||||||
|
print = 1;
|
||||||
|
else
|
||||||
|
dest = ".";
|
||||||
}
|
}
|
||||||
if (*dest == '/' || (path = bltinlookup("CDPATH", 1)) == NULL)
|
if (*dest == '/' || (path = bltinlookup("CDPATH", 1)) == NULL)
|
||||||
path = nullstr;
|
path = nullstr;
|
||||||
while ((p = padvance(&path, dest)) != NULL) {
|
while ((p = padvance(&path, dest)) != NULL) {
|
||||||
if (stat(p, &statb) >= 0
|
if (stat(p, &statb) >= 0 && S_ISDIR(statb.st_mode)) {
|
||||||
&& (statb.st_mode & S_IFMT) == S_IFDIR
|
if (!print) {
|
||||||
&& docd(p, strcmp(p, dest), tohome) >= 0)
|
/*
|
||||||
|
* XXX - rethink
|
||||||
|
*/
|
||||||
|
if (p[0] == '.' && p[1] == '/' && p[2] != '\0')
|
||||||
|
p += 2;
|
||||||
|
print = strcmp(p, dest);
|
||||||
|
}
|
||||||
|
if (docd(p, print, phys) >= 0)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
error("can't cd to %s", dest);
|
error("can't cd to %s", dest);
|
||||||
|
/*NOTREACHED*/
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Actually do the chdir. If the name refers to symbolic links, we
|
* Actually change the directory. In an interactive shell, print the
|
||||||
* compute the actual directory name before doing the cd. In an
|
* directory name if "print" is nonzero.
|
||||||
* interactive shell, print the directory name if "print" is nonzero
|
|
||||||
* or if the name refers to a symbolic link. We also print the name
|
|
||||||
* if "/u/logname" was expanded in it, since this is similar to a
|
|
||||||
* symbolic link. (The check for this breaks if the user gives the
|
|
||||||
* cd command some additional, unused arguments.)
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#if SYMLINKS == 0
|
|
||||||
STATIC int
|
STATIC int
|
||||||
docd(dest, print, tohome)
|
docd(char *dest, int print, int phys)
|
||||||
char *dest;
|
|
||||||
{
|
{
|
||||||
#if UDIR || TILDE
|
|
||||||
if (didudir)
|
TRACE(("docd(\"%s\", %d, %d) called\n", dest, print, phys));
|
||||||
print = 1;
|
|
||||||
#endif
|
/* If logical cd fails, fall back to physical. */
|
||||||
INTOFF;
|
if ((phys || cdlogical(dest) < 0) && cdphysical(dest) < 0)
|
||||||
if (chdir(dest) < 0) {
|
return (-1);
|
||||||
INTON;
|
|
||||||
return -1;
|
if (print && iflag && curdir)
|
||||||
}
|
out1fmt("%s\n", curdir);
|
||||||
updatepwd(dest);
|
|
||||||
INTON;
|
|
||||||
if (print && iflag)
|
|
||||||
out1fmt("%s\n", stackblock());
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
#else
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
STATIC int
|
STATIC int
|
||||||
docd(dest, print, tohome)
|
cdlogical(char *dest)
|
||||||
char *dest;
|
|
||||||
{
|
{
|
||||||
register char *p;
|
char *p;
|
||||||
register char *q;
|
char *q;
|
||||||
char *symlink;
|
|
||||||
char *component;
|
char *component;
|
||||||
struct stat statb;
|
struct stat statb;
|
||||||
int first;
|
int first;
|
||||||
int i;
|
int badstat;
|
||||||
|
|
||||||
TRACE(("docd(\"%s\", %d, %d) called\n", dest, print, tohome));
|
/*
|
||||||
#if UDIR || TILDE
|
* Check each component of the path. If we find a symlink or
|
||||||
if (didudir)
|
* something we can't stat, clear curdir to force a getcwd()
|
||||||
print = 1;
|
* next time we get the value of the current directory.
|
||||||
#endif
|
*/
|
||||||
|
badstat = 0;
|
||||||
top:
|
cdcomppath = stalloc(strlen(dest) + 1);
|
||||||
cdcomppath = dest;
|
scopy(dest, cdcomppath);
|
||||||
STARTSTACKSTR(p);
|
STARTSTACKSTR(p);
|
||||||
if (*dest == '/') {
|
if (*dest == '/') {
|
||||||
STPUTC('/', p);
|
STPUTC('/', p);
|
||||||
|
@ -166,7 +185,7 @@ top:
|
||||||
}
|
}
|
||||||
first = 1;
|
first = 1;
|
||||||
while ((q = getcomponent()) != NULL) {
|
while ((q = getcomponent()) != NULL) {
|
||||||
if (q[0] == '\0' || q[0] == '.' && q[1] == '\0')
|
if (q[0] == '\0' || (q[0] == '.' && q[1] == '\0'))
|
||||||
continue;
|
continue;
|
||||||
if (! first)
|
if (! first)
|
||||||
STPUTC('/', p);
|
STPUTC('/', p);
|
||||||
|
@ -177,71 +196,42 @@ top:
|
||||||
if (equal(component, ".."))
|
if (equal(component, ".."))
|
||||||
continue;
|
continue;
|
||||||
STACKSTRNUL(p);
|
STACKSTRNUL(p);
|
||||||
if (lstat(stackblock(), &statb) < 0)
|
if (lstat(stackblock(), &statb) < 0) {
|
||||||
error("lstat %s failed", stackblock());
|
badstat = 1;
|
||||||
if ((statb.st_mode & S_IFMT) != S_IFLNK)
|
break;
|
||||||
continue;
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* Hit a symbolic link. We have to start all over again. */
|
|
||||||
print = 1;
|
|
||||||
STPUTC('\0', p);
|
|
||||||
symlink = grabstackstr(p);
|
|
||||||
i = (int)statb.st_size + 2; /* 2 for '/' and '\0' */
|
|
||||||
if (cdcomppath != NULL)
|
|
||||||
i += strlen(cdcomppath);
|
|
||||||
p = stalloc(i);
|
|
||||||
if (readlink(symlink, p, (int)statb.st_size) < 0) {
|
|
||||||
error("readlink %s failed", stackblock());
|
|
||||||
}
|
|
||||||
if (cdcomppath != NULL) {
|
|
||||||
p[(int)statb.st_size] = '/';
|
|
||||||
scopy(cdcomppath, p + (int)statb.st_size + 1);
|
|
||||||
} else {
|
|
||||||
p[(int)statb.st_size] = '\0';
|
|
||||||
}
|
|
||||||
if (p[0] != '/') { /* relative path name */
|
|
||||||
char *r;
|
|
||||||
q = r = symlink;
|
|
||||||
while (*q) {
|
|
||||||
if (*q++ == '/')
|
|
||||||
r = q;
|
|
||||||
}
|
|
||||||
*r = '\0';
|
|
||||||
dest = stalloc(strlen(symlink) + strlen(p) + 1);
|
|
||||||
scopy(symlink, dest);
|
|
||||||
strcat(dest, p);
|
|
||||||
} else {
|
|
||||||
dest = p;
|
|
||||||
}
|
|
||||||
goto top;
|
|
||||||
}
|
|
||||||
STPUTC('\0', p);
|
|
||||||
p = grabstackstr(p);
|
|
||||||
INTOFF;
|
INTOFF;
|
||||||
/* The empty string is not a legal argument to chdir on a POSIX 1003.1
|
if (updatepwd(badstat ? NULL : dest) < 0 || chdir(curdir) < 0) {
|
||||||
* system. */
|
|
||||||
if (p[0] != '\0' && chdir(p) < 0) {
|
|
||||||
INTON;
|
INTON;
|
||||||
return -1;
|
return (-1);
|
||||||
}
|
}
|
||||||
updatepwd(p);
|
|
||||||
INTON;
|
INTON;
|
||||||
if (print && !tohome && iflag)
|
return (0);
|
||||||
out1fmt("%s\n", p);
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
#endif /* SYMLINKS */
|
|
||||||
|
|
||||||
|
STATIC int
|
||||||
|
cdphysical(char *dest)
|
||||||
|
{
|
||||||
|
|
||||||
|
INTOFF;
|
||||||
|
if (chdir(dest) < 0 || updatepwd(NULL) < 0) {
|
||||||
|
INTON;
|
||||||
|
return (-1);
|
||||||
|
}
|
||||||
|
INTON;
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Get the next component of the path name pointed to by cdcomppath.
|
* Get the next component of the path name pointed to by cdcomppath.
|
||||||
* This routine overwrites the string pointed to by cdcomppath.
|
* This routine overwrites the string pointed to by cdcomppath.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
STATIC char *
|
STATIC char *
|
||||||
getcomponent() {
|
getcomponent(void)
|
||||||
register char *p;
|
{
|
||||||
|
char *p;
|
||||||
char *start;
|
char *start;
|
||||||
|
|
||||||
if ((p = cdcomppath) == NULL)
|
if ((p = cdcomppath) == NULL)
|
||||||
|
@ -259,29 +249,43 @@ getcomponent() {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Update curdir (the name of the current directory) in response to a
|
* Update curdir (the name of the current directory) in response to a
|
||||||
* cd command. We also call hashcd to let the routines in exec.c know
|
* cd command. We also call hashcd to let the routines in exec.c know
|
||||||
* that the current directory has changed.
|
* that the current directory has changed.
|
||||||
*/
|
*/
|
||||||
|
STATIC int
|
||||||
void hashcd();
|
updatepwd(char *dir)
|
||||||
|
|
||||||
STATIC void
|
|
||||||
updatepwd(dir)
|
|
||||||
char *dir;
|
|
||||||
{
|
{
|
||||||
char *new;
|
char *new;
|
||||||
char *p;
|
char *p;
|
||||||
|
|
||||||
hashcd(); /* update command hash table */
|
hashcd(); /* update command hash table */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If our argument is NULL, we don't know the current directory
|
||||||
|
* any more because we traversed a symbolic link or something
|
||||||
|
* we couldn't stat().
|
||||||
|
*/
|
||||||
|
if (dir == NULL || curdir == NULL) {
|
||||||
|
if (prevdir)
|
||||||
|
ckfree(prevdir);
|
||||||
|
INTOFF;
|
||||||
|
prevdir = curdir;
|
||||||
|
curdir = NULL;
|
||||||
|
if (getpwd() == NULL) {
|
||||||
|
INTON;
|
||||||
|
return (-1);
|
||||||
|
}
|
||||||
|
setvar("PWD", curdir, VEXPORT);
|
||||||
|
setvar("OLDPWD", prevdir, VEXPORT);
|
||||||
|
INTON;
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
cdcomppath = stalloc(strlen(dir) + 1);
|
cdcomppath = stalloc(strlen(dir) + 1);
|
||||||
scopy(dir, cdcomppath);
|
scopy(dir, cdcomppath);
|
||||||
STARTSTACKSTR(new);
|
STARTSTACKSTR(new);
|
||||||
if (*dir != '/') {
|
if (*dir != '/') {
|
||||||
if (curdir == NULL)
|
|
||||||
return;
|
|
||||||
p = curdir;
|
p = curdir;
|
||||||
while (*p)
|
while (*p)
|
||||||
STPUTC(*p++, new);
|
STPUTC(*p++, new);
|
||||||
|
@ -300,73 +304,87 @@ updatepwd(dir)
|
||||||
if (new == stackblock())
|
if (new == stackblock())
|
||||||
STPUTC('/', new);
|
STPUTC('/', new);
|
||||||
STACKSTRNUL(new);
|
STACKSTRNUL(new);
|
||||||
if (curdir)
|
INTOFF;
|
||||||
ckfree(curdir);
|
if (prevdir)
|
||||||
|
ckfree(prevdir);
|
||||||
|
prevdir = curdir;
|
||||||
curdir = savestr(stackblock());
|
curdir = savestr(stackblock());
|
||||||
|
setvar("PWD", curdir, VEXPORT);
|
||||||
|
setvar("OLDPWD", prevdir, VEXPORT);
|
||||||
|
INTON;
|
||||||
|
|
||||||
|
return (0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
int
|
int
|
||||||
pwdcmd(argc, argv) char **argv; {
|
pwdcmd(int argc, char **argv)
|
||||||
getpwd();
|
{
|
||||||
|
char buf[PATH_MAX];
|
||||||
|
int ch, phys;
|
||||||
|
|
||||||
|
optreset = 1; optind = 1; opterr = 0; /* initialize getopt */
|
||||||
|
phys = Pflag;
|
||||||
|
while ((ch = getopt(argc, argv, "LP")) != -1) {
|
||||||
|
switch (ch) {
|
||||||
|
case 'L':
|
||||||
|
phys = 0;
|
||||||
|
break;
|
||||||
|
case 'P':
|
||||||
|
phys = 1;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
error("unknown option: -%c", optopt);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
argc -= optind;
|
||||||
|
argv += optind;
|
||||||
|
|
||||||
|
if (argc != 0)
|
||||||
|
error("too many arguments");
|
||||||
|
|
||||||
|
if (!phys && getpwd()) {
|
||||||
out1str(curdir);
|
out1str(curdir);
|
||||||
out1c('\n');
|
out1c('\n');
|
||||||
|
} else {
|
||||||
|
if (getcwd(buf, sizeof(buf)) == NULL)
|
||||||
|
error(".: %s", strerror(errno));
|
||||||
|
out1str(buf);
|
||||||
|
out1c('\n');
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Run /bin/pwd to find out what the current directory is. We suppress
|
* Find out what the current directory is. If we already know the current
|
||||||
* interrupts throughout most of this, but the user can still break out
|
|
||||||
* of it by killing the pwd program. If we already know the current
|
|
||||||
* directory, this routine returns immediately.
|
* directory, this routine returns immediately.
|
||||||
*/
|
*/
|
||||||
|
char *
|
||||||
#define MAXPWD 256
|
getpwd(void)
|
||||||
|
{
|
||||||
STATIC void
|
char buf[PATH_MAX];
|
||||||
getpwd() {
|
|
||||||
char buf[MAXPWD];
|
|
||||||
char *p;
|
|
||||||
int i;
|
|
||||||
int status;
|
|
||||||
struct job *jp;
|
|
||||||
int pip[2];
|
|
||||||
|
|
||||||
if (curdir)
|
if (curdir)
|
||||||
return;
|
return curdir;
|
||||||
INTOFF;
|
if (getcwd(buf, sizeof(buf)) == NULL) {
|
||||||
if (pipe(pip) < 0)
|
char *pwd = getenv("PWD");
|
||||||
error("Pipe call failed");
|
struct stat stdot, stpwd;
|
||||||
jp = makejob((union node *)NULL, 1);
|
|
||||||
if (forkshell(jp, (union node *)NULL, FORK_NOJOB) == 0) {
|
if (pwd && *pwd == '/' && stat(".", &stdot) != -1 &&
|
||||||
close(pip[0]);
|
stat(pwd, &stpwd) != -1 &&
|
||||||
if (pip[1] != 1) {
|
stdot.st_dev == stpwd.st_dev &&
|
||||||
close(1);
|
stdot.st_ino == stpwd.st_ino) {
|
||||||
copyfd(pip[1], 1);
|
curdir = savestr(pwd);
|
||||||
close(pip[1]);
|
return curdir;
|
||||||
}
|
}
|
||||||
execl("/bin/pwd", "pwd", (char *)0);
|
return NULL;
|
||||||
error("Cannot exec /bin/pwd");
|
|
||||||
}
|
}
|
||||||
close(pip[1]);
|
|
||||||
pip[1] = -1;
|
|
||||||
p = buf;
|
|
||||||
while ((i = read(pip[0], p, buf + MAXPWD - p)) > 0
|
|
||||||
|| i == -1 && errno == EINTR) {
|
|
||||||
if (i > 0)
|
|
||||||
p += i;
|
|
||||||
}
|
|
||||||
close(pip[0]);
|
|
||||||
pip[0] = -1;
|
|
||||||
status = waitforjob(jp);
|
|
||||||
if (status != 0)
|
|
||||||
error((char *)0);
|
|
||||||
if (i < 0 || p == buf || p[-1] != '\n')
|
|
||||||
error("pwd command failed");
|
|
||||||
p[-1] = '\0';
|
|
||||||
curdir = savestr(buf);
|
curdir = savestr(buf);
|
||||||
INTON;
|
|
||||||
|
return curdir;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* $PchId: cd.c,v 1.6 2006/05/22 12:42:03 philip Exp $
|
||||||
|
*/
|
||||||
|
|
38
commands/ash/cd.h
Normal file
38
commands/ash/cd.h
Normal file
|
@ -0,0 +1,38 @@
|
||||||
|
/*-
|
||||||
|
* Copyright (c) 1995
|
||||||
|
* The Regents of the University of California. All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
* 1. Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* 4. Neither the name of the University nor the names of its contributors
|
||||||
|
* may be used to endorse or promote products derived from this software
|
||||||
|
* without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||||
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||||
|
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
|
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||||
|
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||||
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||||
|
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||||
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||||
|
* SUCH DAMAGE.
|
||||||
|
*
|
||||||
|
* $FreeBSD: src/bin/sh/cd.h,v 1.7 2004/04/06 20:06:51 markm Exp $
|
||||||
|
*/
|
||||||
|
|
||||||
|
char *getpwd(void);
|
||||||
|
int cdcmd (int, char **);
|
||||||
|
int pwdcmd(int, char **);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* $PchId: cd.h,v 1.3 2006/03/31 09:59:04 philip Exp $
|
||||||
|
*/
|
354
commands/ash/complete.c
Normal file
354
commands/ash/complete.c
Normal file
|
@ -0,0 +1,354 @@
|
||||||
|
/*
|
||||||
|
complete.c
|
||||||
|
|
||||||
|
Created: July 1995 by Philip Homburg <philip@cs.vu.nl>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <ctype.h>
|
||||||
|
#include <dirent.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include "myhistedit.h"
|
||||||
|
#include "shell.h"
|
||||||
|
|
||||||
|
#include "complete.h"
|
||||||
|
#include "error.h"
|
||||||
|
#include "expand.h"
|
||||||
|
#include "nodes.h"
|
||||||
|
#include "memalloc.h"
|
||||||
|
|
||||||
|
static char **getlist(EditLine *el, int *baselen, int *isdir);
|
||||||
|
static char **getlist_tilde(char *prefix);
|
||||||
|
static int vstrcmp(const void *v1, const void *v2);
|
||||||
|
static void print_list(char **list);
|
||||||
|
static int install_extra(EditLine *el, char **list, int baselen, int isdir);
|
||||||
|
|
||||||
|
unsigned char complete(EditLine *el, int ch)
|
||||||
|
{
|
||||||
|
struct stackmark mark;
|
||||||
|
const LineInfo *lf;
|
||||||
|
char **list;
|
||||||
|
int baselen, prefix, isdir;
|
||||||
|
|
||||||
|
/* Direct the cursor the the end of the word. */
|
||||||
|
for(;;)
|
||||||
|
{
|
||||||
|
lf = el_line(el);
|
||||||
|
if (lf->cursor < lf->lastchar &&
|
||||||
|
!isspace((unsigned char)*lf->cursor))
|
||||||
|
{
|
||||||
|
(*(char **)&lf->cursor)++; /* XXX */
|
||||||
|
}
|
||||||
|
else
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
setstackmark(&mark);
|
||||||
|
list= getlist(el, &baselen, &isdir);
|
||||||
|
if (list)
|
||||||
|
{
|
||||||
|
prefix= install_extra(el, list, baselen, isdir);
|
||||||
|
el_push(el, "i");
|
||||||
|
}
|
||||||
|
popstackmark(&mark);
|
||||||
|
if (list)
|
||||||
|
return CC_REFRESH;
|
||||||
|
else
|
||||||
|
return CC_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned char complete_list(EditLine *el, int ch)
|
||||||
|
{
|
||||||
|
struct stackmark mark;
|
||||||
|
char **list;
|
||||||
|
|
||||||
|
setstackmark(&mark);
|
||||||
|
list= getlist(el, NULL, NULL);
|
||||||
|
if (list)
|
||||||
|
{
|
||||||
|
print_list(list);
|
||||||
|
re_goto_bottom(el);
|
||||||
|
}
|
||||||
|
popstackmark(&mark);
|
||||||
|
if (list)
|
||||||
|
{
|
||||||
|
return CC_REFRESH;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return CC_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned char complete_or_list(EditLine *el, int ch)
|
||||||
|
{
|
||||||
|
struct stackmark mark;
|
||||||
|
const LineInfo *lf;
|
||||||
|
char **list;
|
||||||
|
int baselen, prefix, isdir;
|
||||||
|
|
||||||
|
setstackmark(&mark);
|
||||||
|
list= getlist(el, &baselen, &isdir);
|
||||||
|
if (list)
|
||||||
|
{
|
||||||
|
prefix= install_extra(el, list, baselen, isdir);
|
||||||
|
if (prefix == baselen)
|
||||||
|
{
|
||||||
|
print_list(list);
|
||||||
|
re_goto_bottom(el);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
popstackmark(&mark);
|
||||||
|
if (list)
|
||||||
|
return CC_REFRESH;
|
||||||
|
else
|
||||||
|
return CC_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned char complete_expand(EditLine *el, int ch)
|
||||||
|
{
|
||||||
|
printf("complete_expand\n");
|
||||||
|
return CC_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
static char **getlist(EditLine *el, int *baselen, int *isdir)
|
||||||
|
{
|
||||||
|
const LineInfo *lf;
|
||||||
|
const char *begin, *end;
|
||||||
|
char *dirnam, *basenam;
|
||||||
|
union node arg;
|
||||||
|
struct arglist arglist;
|
||||||
|
DIR *dir;
|
||||||
|
struct dirent *dirent;
|
||||||
|
int i, l, n;
|
||||||
|
char *p, **list;
|
||||||
|
struct strlist *slp, *nslp;
|
||||||
|
struct stat sb;
|
||||||
|
|
||||||
|
lf = el_line(el);
|
||||||
|
|
||||||
|
/* Try to find to begin and end of the word that we have to comple. */
|
||||||
|
begin= lf->cursor;
|
||||||
|
while (begin > lf->buffer && !isspace((unsigned char)begin[-1]))
|
||||||
|
begin--;
|
||||||
|
end= lf->cursor;
|
||||||
|
while (end < lf->lastchar && !isspace((unsigned char)end[0]))
|
||||||
|
end++;
|
||||||
|
|
||||||
|
*(const char **)&lf->cursor= end; /* XXX */
|
||||||
|
|
||||||
|
/* Copy the word to a string */
|
||||||
|
dirnam= stalloc(end-begin+1);
|
||||||
|
strncpy(dirnam, begin, end-begin);
|
||||||
|
dirnam[end-begin]= '\0';
|
||||||
|
|
||||||
|
/* Cut the word in two pieces: a path and a (partial) component. */
|
||||||
|
basenam= strrchr(dirnam, '/');
|
||||||
|
if (basenam)
|
||||||
|
{
|
||||||
|
basenam++;
|
||||||
|
p= stalloc(strlen(basenam) + 1);
|
||||||
|
strcpy(p, basenam);
|
||||||
|
*basenam= '\0';
|
||||||
|
basenam= p;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (dirnam[0] == '~')
|
||||||
|
return getlist_tilde(dirnam);
|
||||||
|
basenam= dirnam;
|
||||||
|
dirnam= "./";
|
||||||
|
}
|
||||||
|
if (baselen)
|
||||||
|
*baselen= strlen(basenam);
|
||||||
|
|
||||||
|
arg.type= NARG;
|
||||||
|
arg.narg.next= NULL;
|
||||||
|
arg.narg.text= dirnam;
|
||||||
|
arg.narg.backquote= NULL;
|
||||||
|
arglist.list= NULL;
|
||||||
|
arglist.lastp= &arglist.list;
|
||||||
|
expandarg(&arg, &arglist, EXP_TILDE);
|
||||||
|
|
||||||
|
INTOFF;
|
||||||
|
list= NULL;
|
||||||
|
dir= opendir(arglist.list->text);
|
||||||
|
if (dir)
|
||||||
|
{
|
||||||
|
slp= NULL;
|
||||||
|
n= 0;
|
||||||
|
l= strlen(basenam);
|
||||||
|
while(dirent= readdir(dir))
|
||||||
|
{
|
||||||
|
if (strncmp(dirent->d_name, basenam, l) != 0)
|
||||||
|
continue;
|
||||||
|
if (l == 0 && dirent->d_name[0] == '.')
|
||||||
|
continue;
|
||||||
|
nslp= stalloc(sizeof(*nslp));
|
||||||
|
nslp->next= slp;
|
||||||
|
slp= nslp;
|
||||||
|
slp->text= stalloc(strlen(dirent->d_name)+1);
|
||||||
|
strcpy(slp->text, dirent->d_name);
|
||||||
|
n++;
|
||||||
|
if (n == 1 && isdir != NULL)
|
||||||
|
{
|
||||||
|
/* Try to findout whether this entry is a
|
||||||
|
* file or a directory.
|
||||||
|
*/
|
||||||
|
p= stalloc(strlen(arglist.list->text) +
|
||||||
|
strlen(dirent->d_name) + 1);
|
||||||
|
strcpy(p, arglist.list->text);
|
||||||
|
strcat(p, dirent->d_name);
|
||||||
|
if (stat(p, &sb) == -1)
|
||||||
|
printf("stat '%s' failed: %s\n",
|
||||||
|
p, strerror(errno));
|
||||||
|
if (stat(p, &sb) == 0 && S_ISDIR(sb.st_mode))
|
||||||
|
*isdir= 1;
|
||||||
|
else
|
||||||
|
*isdir= 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
closedir(dir);
|
||||||
|
if (n != 0)
|
||||||
|
{
|
||||||
|
list= stalloc((n+1)*sizeof(*list));
|
||||||
|
for(i= 0; slp; i++, slp= slp->next)
|
||||||
|
list[i]= slp->text;
|
||||||
|
if (i != n)
|
||||||
|
error("complete'make_list: i != n");
|
||||||
|
list[i]= NULL;
|
||||||
|
qsort(list, n, sizeof(*list), vstrcmp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
INTON;
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
|
||||||
|
static char **getlist_tilde(char *prefix)
|
||||||
|
{
|
||||||
|
printf("should ~-complete '%s'\n", prefix);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int vstrcmp(const void *v1, const void *v2)
|
||||||
|
{
|
||||||
|
return strcmp(*(char **)v1, *(char **)v2);
|
||||||
|
}
|
||||||
|
|
||||||
|
#define MAXCOLS 40
|
||||||
|
#define SEPWIDTH 4
|
||||||
|
|
||||||
|
static void print_list(char **list)
|
||||||
|
{
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
int cols;
|
||||||
|
int start[MAXCOLS+1];
|
||||||
|
int width[MAXCOLS];
|
||||||
|
} best, next;
|
||||||
|
int e, i, j, l, n, o, cols, maxw, width;
|
||||||
|
int linewidth= 80;
|
||||||
|
|
||||||
|
/* Count the number of entries. */
|
||||||
|
for (n= 0; list[n]; n++)
|
||||||
|
; /* do nothing */
|
||||||
|
if (n == 0)
|
||||||
|
error("complete'print_list: n= 0");
|
||||||
|
|
||||||
|
/* Try to maximize the number of columns */
|
||||||
|
for (cols= 1; cols<= MAXCOLS; cols++)
|
||||||
|
{
|
||||||
|
next.cols= cols;
|
||||||
|
|
||||||
|
o= 0;
|
||||||
|
width= 0;
|
||||||
|
for(j= 0; j<cols; j++)
|
||||||
|
{
|
||||||
|
next.start[j]= o;
|
||||||
|
|
||||||
|
/* Number of entries in this column. */
|
||||||
|
e= (n-o)/(cols-j);
|
||||||
|
if ((n-o)%(cols-j))
|
||||||
|
e++;
|
||||||
|
|
||||||
|
maxw= 0;
|
||||||
|
for (i= 0; i<e; i++)
|
||||||
|
{
|
||||||
|
l= strlen(list[o+i]);
|
||||||
|
if (l < 6)
|
||||||
|
l= 6;
|
||||||
|
l += SEPWIDTH;
|
||||||
|
if (l > maxw)
|
||||||
|
maxw= l;
|
||||||
|
}
|
||||||
|
next.width[j]= maxw;
|
||||||
|
width += maxw;
|
||||||
|
o += e;
|
||||||
|
}
|
||||||
|
next.start[j]= o;
|
||||||
|
if (cols > 1 && width-SEPWIDTH>linewidth)
|
||||||
|
break;
|
||||||
|
best= next;
|
||||||
|
}
|
||||||
|
cols= best.cols;
|
||||||
|
e= best.start[1];
|
||||||
|
printf("\n");
|
||||||
|
for(i= 0; i<e; i++)
|
||||||
|
{
|
||||||
|
for (j= 0; j<cols; j++)
|
||||||
|
{
|
||||||
|
if (best.start[j]+i == best.start[j+1])
|
||||||
|
continue;
|
||||||
|
if (j < cols-1)
|
||||||
|
{
|
||||||
|
printf("%-*s", best.width[j],
|
||||||
|
list[best.start[j]+i]);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
printf("%s", list[best.start[j]+i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (i < e-1)
|
||||||
|
printf("\n");
|
||||||
|
}
|
||||||
|
fflush(stdout);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int install_extra(EditLine *el, char **list, int baselen, int isdir)
|
||||||
|
{
|
||||||
|
int l;
|
||||||
|
char *p, **lp;
|
||||||
|
|
||||||
|
l= strlen(list[0]);
|
||||||
|
for (lp= &list[1]; *lp; lp++)
|
||||||
|
{
|
||||||
|
while(l>0)
|
||||||
|
{
|
||||||
|
if (strncmp(list[0], *lp, l) != 0)
|
||||||
|
l--;
|
||||||
|
else
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (l > baselen || list[1] == NULL)
|
||||||
|
{
|
||||||
|
p= stalloc(l-baselen+2);
|
||||||
|
strncpy(p, list[0]+baselen, l-baselen);
|
||||||
|
if (list[1] == NULL)
|
||||||
|
{
|
||||||
|
p[l-baselen]= isdir ? '/' : ' ';
|
||||||
|
p[l-baselen+1]= '\0';
|
||||||
|
l++;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
p[l-baselen]= '\0';
|
||||||
|
if (el_insertstr(el, p) == -1)
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return l;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* $PchId: complete.c,v 1.2 2006/04/10 14:35:53 philip Exp $
|
||||||
|
*/
|
14
commands/ash/complete.h
Normal file
14
commands/ash/complete.h
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
/*
|
||||||
|
complete.h
|
||||||
|
|
||||||
|
Created: July 1995 by Philip Homburg <philip@cs.vu.nl>
|
||||||
|
*/
|
||||||
|
|
||||||
|
unsigned char complete(EditLine *el, int ch);
|
||||||
|
unsigned char complete_list(EditLine *el, int ch);
|
||||||
|
unsigned char complete_or_list(EditLine *el, int ch);
|
||||||
|
unsigned char complete_expand(EditLine *el, int ch);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* $PchId: complete.h,v 1.1 2001/05/17 07:12:05 philip Exp $
|
||||||
|
*/
|
|
@ -1,194 +0,0 @@
|
||||||
/*-
|
|
||||||
* Copyright (c) 1991 The Regents of the University of California.
|
|
||||||
* All rights reserved.
|
|
||||||
*
|
|
||||||
* This code is derived from software contributed to Berkeley by
|
|
||||||
* Kenneth Almquist.
|
|
||||||
*
|
|
||||||
* Redistribution and use in source and binary forms, with or without
|
|
||||||
* modification, are permitted provided that the following conditions
|
|
||||||
* are met:
|
|
||||||
* 1. Redistributions of source code must retain the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer.
|
|
||||||
* 2. Redistributions in binary form must reproduce the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer in the
|
|
||||||
* documentation and/or other materials provided with the distribution.
|
|
||||||
* 3. All advertising materials mentioning features or use of this software
|
|
||||||
* must display the following acknowledgement:
|
|
||||||
* This product includes software developed by the University of
|
|
||||||
* California, Berkeley and its contributors.
|
|
||||||
* 4. Neither the name of the University nor the names of its contributors
|
|
||||||
* may be used to endorse or promote products derived from this software
|
|
||||||
* without specific prior written permission.
|
|
||||||
*
|
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
|
||||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
||||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
||||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
|
||||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
||||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
|
||||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
|
||||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
|
||||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
|
||||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
|
||||||
* SUCH DAMAGE.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef lint
|
|
||||||
static char sccsid[] = "@(#)dirent.c 5.1 (Berkeley) 3/7/91";
|
|
||||||
#endif /* not lint */
|
|
||||||
|
|
||||||
#include "shell.h" /* definitions for pointer, NULL, DIRENT, and BSD */
|
|
||||||
|
|
||||||
#if ! DIRENT
|
|
||||||
|
|
||||||
#include <errno.h>
|
|
||||||
#include <sys/types.h>
|
|
||||||
#include <sys/stat.h>
|
|
||||||
#include <fcntl.h>
|
|
||||||
#include <dirent.h>
|
|
||||||
|
|
||||||
#ifndef S_ISDIR /* macro to test for directory file */
|
|
||||||
#define S_ISDIR(mode) (((mode) & S_IFMT) == S_IFDIR)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef BSD
|
|
||||||
|
|
||||||
#ifdef __STDC__
|
|
||||||
int stat(char *, struct stat *);
|
|
||||||
#else
|
|
||||||
int stat();
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* The BSD opendir routine doesn't check that what is being opened is a
|
|
||||||
* directory, so we have to include the check in a wrapper routine.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#undef opendir
|
|
||||||
|
|
||||||
DIR *
|
|
||||||
myopendir(dirname)
|
|
||||||
char *dirname; /* name of directory */
|
|
||||||
{
|
|
||||||
struct stat statb;
|
|
||||||
|
|
||||||
if (stat(dirname, &statb) != 0 || ! S_ISDIR(statb.st_mode)) {
|
|
||||||
errno = ENOTDIR;
|
|
||||||
return NULL; /* not a directory */
|
|
||||||
}
|
|
||||||
return opendir(dirname);
|
|
||||||
}
|
|
||||||
|
|
||||||
#else /* not BSD */
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Dirent routines for old style file systems.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifdef __STDC__
|
|
||||||
pointer malloc(unsigned);
|
|
||||||
void free(pointer);
|
|
||||||
int open(char *, int, ...);
|
|
||||||
int close(int);
|
|
||||||
int fstat(int, struct stat *);
|
|
||||||
#else
|
|
||||||
pointer malloc();
|
|
||||||
void free();
|
|
||||||
int open();
|
|
||||||
int close();
|
|
||||||
int fstat();
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
DIR *
|
|
||||||
opendir(dirname)
|
|
||||||
char *dirname; /* name of directory */
|
|
||||||
{
|
|
||||||
register DIR *dirp; /* -> malloc'ed storage */
|
|
||||||
register int fd; /* file descriptor for read */
|
|
||||||
struct stat statb; /* result of fstat() */
|
|
||||||
|
|
||||||
#ifdef O_NDELAY
|
|
||||||
fd = open(dirname, O_RDONLY|O_NDELAY);
|
|
||||||
#else
|
|
||||||
fd = open(dirname, O_RDONLY);
|
|
||||||
#endif
|
|
||||||
if (fd < 0)
|
|
||||||
return NULL; /* errno set by open() */
|
|
||||||
|
|
||||||
if (fstat(fd, &statb) != 0 || !S_ISDIR(statb.st_mode)) {
|
|
||||||
(void)close(fd);
|
|
||||||
errno = ENOTDIR;
|
|
||||||
return NULL; /* not a directory */
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((dirp = (DIR *)malloc(sizeof(DIR))) == NULL) {
|
|
||||||
(void)close(fd);
|
|
||||||
errno = ENOMEM;
|
|
||||||
return NULL; /* not enough memory */
|
|
||||||
}
|
|
||||||
|
|
||||||
dirp->dd_fd = fd;
|
|
||||||
dirp->dd_nleft = 0; /* refill needed */
|
|
||||||
|
|
||||||
return dirp;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
int
|
|
||||||
closedir(dirp)
|
|
||||||
register DIR *dirp; /* stream from opendir() */
|
|
||||||
{
|
|
||||||
register int fd;
|
|
||||||
|
|
||||||
if (dirp == NULL) {
|
|
||||||
errno = EFAULT;
|
|
||||||
return -1; /* invalid pointer */
|
|
||||||
}
|
|
||||||
|
|
||||||
fd = dirp->dd_fd;
|
|
||||||
free((pointer)dirp);
|
|
||||||
return close(fd);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
struct dirent *
|
|
||||||
readdir(dirp)
|
|
||||||
register DIR *dirp; /* stream from opendir() */
|
|
||||||
{
|
|
||||||
register struct direct *dp;
|
|
||||||
register char *p, *q;
|
|
||||||
register int i;
|
|
||||||
|
|
||||||
do {
|
|
||||||
if ((dirp->dd_nleft -= sizeof (struct direct)) < 0) {
|
|
||||||
if ((i = read(dirp->dd_fd,
|
|
||||||
(char *)dirp->dd_buf,
|
|
||||||
DIRBUFENT*sizeof(struct direct))) <= 0) {
|
|
||||||
if (i == 0)
|
|
||||||
errno = 0; /* unnecessary */
|
|
||||||
return NULL; /* EOF or error */
|
|
||||||
}
|
|
||||||
dirp->dd_loc = dirp->dd_buf;
|
|
||||||
dirp->dd_nleft = i - sizeof (struct direct);
|
|
||||||
}
|
|
||||||
dp = dirp->dd_loc++;
|
|
||||||
} while (dp->d_ino == 0);
|
|
||||||
dirp->dd_entry.d_ino = dp->d_ino;
|
|
||||||
|
|
||||||
/* now copy the name, nul terminating it */
|
|
||||||
p = dp->d_name;
|
|
||||||
q = dirp->dd_entry.d_name;
|
|
||||||
i = DIRSIZ;
|
|
||||||
while (--i >= 0 && *p != '\0')
|
|
||||||
*q++ = *p++;
|
|
||||||
*q = '\0';
|
|
||||||
return &dirp->dd_entry;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif /* BSD */
|
|
||||||
#endif /* DIRENT */
|
|
127
commands/ash/errmsg.c
Normal file
127
commands/ash/errmsg.c
Normal file
|
@ -0,0 +1,127 @@
|
||||||
|
/*-
|
||||||
|
* Copyright (c) 1991, 1993
|
||||||
|
* The Regents of the University of California. All rights reserved.
|
||||||
|
*
|
||||||
|
* This code is derived from software contributed to Berkeley by
|
||||||
|
* Kenneth Almquist.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
* 1. Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* 3. All advertising materials mentioning features or use of this software
|
||||||
|
* must display the following acknowledgement:
|
||||||
|
* This product includes software developed by the University of
|
||||||
|
* California, Berkeley and its contributors.
|
||||||
|
* 4. Neither the name of the University nor the names of its contributors
|
||||||
|
* may be used to endorse or promote products derived from this software
|
||||||
|
* without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||||
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||||
|
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
|
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||||
|
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||||
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||||
|
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||||
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||||
|
* SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef lint
|
||||||
|
static char sccsid[] = "@(#)errmsg.c 8.1 (Berkeley) 5/31/93";
|
||||||
|
#endif /* not lint */
|
||||||
|
|
||||||
|
#include "shell.h"
|
||||||
|
#include "output.h"
|
||||||
|
#include "errmsg.h"
|
||||||
|
#include <errno.h>
|
||||||
|
|
||||||
|
|
||||||
|
#define ALL (E_OPEN|E_CREAT|E_EXEC)
|
||||||
|
|
||||||
|
|
||||||
|
struct errname {
|
||||||
|
short errcode; /* error number */
|
||||||
|
short action; /* operation which encountered the error */
|
||||||
|
char *msg; /* text describing the error */
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
STATIC const struct errname errormsg[] = {
|
||||||
|
EINTR, ALL, "interrupted",
|
||||||
|
EACCES, ALL, "permission denied",
|
||||||
|
EIO, ALL, "I/O error",
|
||||||
|
ENOENT, E_OPEN, "no such file",
|
||||||
|
ENOENT, E_CREAT, "directory nonexistent",
|
||||||
|
ENOENT, E_EXEC, "not found",
|
||||||
|
ENOTDIR, E_OPEN, "no such file",
|
||||||
|
ENOTDIR, E_CREAT, "directory nonexistent",
|
||||||
|
ENOTDIR, E_EXEC, "not found",
|
||||||
|
EISDIR, ALL, "is a directory",
|
||||||
|
/* EMFILE, ALL, "too many open files", */
|
||||||
|
ENFILE, ALL, "file table overflow",
|
||||||
|
ENOSPC, ALL, "file system full",
|
||||||
|
#ifdef EDQUOT
|
||||||
|
EDQUOT, ALL, "disk quota exceeded",
|
||||||
|
#endif
|
||||||
|
#ifdef ENOSR
|
||||||
|
ENOSR, ALL, "no streams resources",
|
||||||
|
#endif
|
||||||
|
ENXIO, ALL, "no such device or address",
|
||||||
|
EROFS, ALL, "read-only file system",
|
||||||
|
ETXTBSY, ALL, "text busy",
|
||||||
|
#ifdef SYSV
|
||||||
|
EAGAIN, E_EXEC, "not enough memory",
|
||||||
|
#endif
|
||||||
|
ENOMEM, ALL, "not enough memory",
|
||||||
|
#ifdef ENOLINK
|
||||||
|
ENOLINK, ALL, "remote access failed"
|
||||||
|
#endif
|
||||||
|
#ifdef EMULTIHOP
|
||||||
|
EMULTIHOP, ALL, "remote access failed",
|
||||||
|
#endif
|
||||||
|
#ifdef ECOMM
|
||||||
|
ECOMM, ALL, "remote access failed",
|
||||||
|
#endif
|
||||||
|
#ifdef ESTALE
|
||||||
|
ESTALE, ALL, "remote access failed",
|
||||||
|
#endif
|
||||||
|
#ifdef ETIMEDOUT
|
||||||
|
ETIMEDOUT, ALL, "remote access failed",
|
||||||
|
#endif
|
||||||
|
#ifdef ELOOP
|
||||||
|
ELOOP, ALL, "symbolic link loop",
|
||||||
|
#endif
|
||||||
|
E2BIG, E_EXEC, "argument list too long",
|
||||||
|
#ifdef ELIBACC
|
||||||
|
ELIBACC, E_EXEC, "shared library missing",
|
||||||
|
#endif
|
||||||
|
0, 0, NULL
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Return a string describing an error. The returned string may be a
|
||||||
|
* pointer to a static buffer that will be overwritten on the next call.
|
||||||
|
* Action describes the operation that got the error.
|
||||||
|
*/
|
||||||
|
|
||||||
|
char *
|
||||||
|
errmsg(e, action) {
|
||||||
|
struct errname const *ep;
|
||||||
|
static char buf[12];
|
||||||
|
|
||||||
|
for (ep = errormsg ; ep->errcode ; ep++) {
|
||||||
|
if (ep->errcode == e && (ep->action & action) != 0)
|
||||||
|
return ep->msg;
|
||||||
|
}
|
||||||
|
fmtstr(buf, sizeof buf, "error %d", e);
|
||||||
|
return buf;
|
||||||
|
}
|
47
commands/ash/errmsg.h
Normal file
47
commands/ash/errmsg.h
Normal file
|
@ -0,0 +1,47 @@
|
||||||
|
/*-
|
||||||
|
* Copyright (c) 1991, 1993
|
||||||
|
* The Regents of the University of California. All rights reserved.
|
||||||
|
*
|
||||||
|
* This code is derived from software contributed to Berkeley by
|
||||||
|
* Kenneth Almquist.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
* 1. Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* 3. All advertising materials mentioning features or use of this software
|
||||||
|
* must display the following acknowledgement:
|
||||||
|
* This product includes software developed by the University of
|
||||||
|
* California, Berkeley and its contributors.
|
||||||
|
* 4. Neither the name of the University nor the names of its contributors
|
||||||
|
* may be used to endorse or promote products derived from this software
|
||||||
|
* without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||||
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||||
|
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
|
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||||
|
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||||
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||||
|
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||||
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||||
|
* SUCH DAMAGE.
|
||||||
|
*
|
||||||
|
* @(#)errmsg.h 8.1 (Berkeley) 5/31/93
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define E_OPEN 01
|
||||||
|
#define E_CREAT 02
|
||||||
|
#define E_EXEC 04
|
||||||
|
|
||||||
|
#ifdef __STDC__
|
||||||
|
char *errmsg(int, int);
|
||||||
|
#else
|
||||||
|
char *errmsg();
|
||||||
|
#endif
|
|
@ -1,6 +1,6 @@
|
||||||
/*-
|
/*-
|
||||||
* Copyright (c) 1991 The Regents of the University of California.
|
* Copyright (c) 1991, 1993
|
||||||
* All rights reserved.
|
* The Regents of the University of California. All rights reserved.
|
||||||
*
|
*
|
||||||
* This code is derived from software contributed to Berkeley by
|
* This code is derived from software contributed to Berkeley by
|
||||||
* Kenneth Almquist.
|
* Kenneth Almquist.
|
||||||
|
@ -13,10 +13,6 @@
|
||||||
* 2. Redistributions in binary form must reproduce the above copyright
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
* notice, this list of conditions and the following disclaimer in the
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
* documentation and/or other materials provided with the distribution.
|
* documentation and/or other materials provided with the distribution.
|
||||||
* 3. All advertising materials mentioning features or use of this software
|
|
||||||
* must display the following acknowledgement:
|
|
||||||
* This product includes software developed by the University of
|
|
||||||
* California, Berkeley and its contributors.
|
|
||||||
* 4. Neither the name of the University nor the names of its contributors
|
* 4. Neither the name of the University nor the names of its contributors
|
||||||
* may be used to endorse or promote products derived from this software
|
* may be used to endorse or promote products derived from this software
|
||||||
* without specific prior written permission.
|
* without specific prior written permission.
|
||||||
|
@ -35,8 +31,14 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef lint
|
#ifndef lint
|
||||||
static char sccsid[] = "@(#)error.c 5.1 (Berkeley) 3/7/91";
|
#if 0
|
||||||
|
static char sccsid[] = "@(#)error.c 8.2 (Berkeley) 5/4/95";
|
||||||
|
#endif
|
||||||
#endif /* not lint */
|
#endif /* not lint */
|
||||||
|
/*
|
||||||
|
#include <sys/cdefs.h>
|
||||||
|
__FBSDID("$FreeBSD: src/bin/sh/error.c,v 1.25 2004/04/06 20:06:51 markm Exp $");
|
||||||
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Errors and exceptions.
|
* Errors and exceptions.
|
||||||
|
@ -47,14 +49,14 @@ static char sccsid[] = "@(#)error.c 5.1 (Berkeley) 3/7/91";
|
||||||
#include "options.h"
|
#include "options.h"
|
||||||
#include "output.h"
|
#include "output.h"
|
||||||
#include "error.h"
|
#include "error.h"
|
||||||
#include <sys/types.h>
|
#include "nodes.h" /* show.h needs nodes.h */
|
||||||
|
#include "show.h"
|
||||||
|
#include "trap.h"
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
#ifdef __STDC__
|
#include <stdlib.h>
|
||||||
#include "stdarg.h"
|
#include <unistd.h>
|
||||||
#else
|
|
||||||
#include <varargs.h>
|
|
||||||
#endif
|
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -62,12 +64,14 @@ static char sccsid[] = "@(#)error.c 5.1 (Berkeley) 3/7/91";
|
||||||
*/
|
*/
|
||||||
|
|
||||||
struct jmploc *handler;
|
struct jmploc *handler;
|
||||||
int exception;
|
volatile sig_atomic_t exception;
|
||||||
volatile int suppressint;
|
volatile sig_atomic_t suppressint;
|
||||||
volatile int intpending;
|
volatile sig_atomic_t intpending;
|
||||||
char *commandname;
|
char *commandname;
|
||||||
|
|
||||||
|
|
||||||
|
static void exverror(int, const char *, va_list) __printf0like(2, 0);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Called to raise an exception. Since C doesn't include exceptions, we
|
* Called to raise an exception. Since C doesn't include exceptions, we
|
||||||
* just do a longjmp to the exception handler. The type of exception is
|
* just do a longjmp to the exception handler. The type of exception is
|
||||||
|
@ -75,7 +79,8 @@ char *commandname;
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void
|
void
|
||||||
exraise(e) {
|
exraise(int e)
|
||||||
|
{
|
||||||
if (handler == NULL)
|
if (handler == NULL)
|
||||||
abort();
|
abort();
|
||||||
exception = e;
|
exception = e;
|
||||||
|
@ -87,69 +92,63 @@ exraise(e) {
|
||||||
* Called from trap.c when a SIGINT is received. (If the user specifies
|
* Called from trap.c when a SIGINT is received. (If the user specifies
|
||||||
* that SIGINT is to be trapped or ignored using the trap builtin, then
|
* that SIGINT is to be trapped or ignored using the trap builtin, then
|
||||||
* this routine is not called.) Suppressint is nonzero when interrupts
|
* this routine is not called.) Suppressint is nonzero when interrupts
|
||||||
* are held using the INTOFF macro. The call to _exit is necessary because
|
* are held using the INTOFF macro. If SIGINTs are not suppressed and
|
||||||
* there is a short period after a fork before the signal handlers are
|
* the shell is not a root shell, then we want to be terminated if we
|
||||||
* set to the appropriate value for the child. (The test for iflag is
|
* get here, as if we were terminated directly by a SIGINT. Arrange for
|
||||||
* just defensive programming.)
|
* this here.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void
|
void
|
||||||
onint() {
|
onint(void)
|
||||||
if (suppressint) {
|
{
|
||||||
|
sigset_t sigset;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The !in_dotrap here is safe. The only way we can arrive here
|
||||||
|
* with in_dotrap set is that a trap handler set SIGINT to SIG_DFL
|
||||||
|
* and killed itself.
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (suppressint && !in_dotrap) {
|
||||||
intpending++;
|
intpending++;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
intpending = 0;
|
intpending = 0;
|
||||||
#ifdef BSD
|
sigemptyset(&sigset);
|
||||||
sigsetmask(0);
|
sigprocmask(SIG_SETMASK, &sigset, NULL);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This doesn't seem to be needed, since main() emits a newline.
|
||||||
|
*/
|
||||||
|
#if 0
|
||||||
|
if (tcgetpgrp(0) == getpid())
|
||||||
|
write(STDERR_FILENO, "\n", 1);
|
||||||
#endif
|
#endif
|
||||||
if (rootshell && iflag)
|
if (rootshell && iflag)
|
||||||
exraise(EXINT);
|
exraise(EXINT);
|
||||||
else
|
else {
|
||||||
_exit(128 + SIGINT);
|
signal(SIGINT, SIG_DFL);
|
||||||
|
kill(getpid(), SIGINT);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void
|
|
||||||
error2(a, b)
|
|
||||||
char *a, *b;
|
|
||||||
{
|
|
||||||
error("%s: %s", a, b);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Error is called to raise the error exception. If the first argument
|
* Exverror is called to raise the error exception. If the first argument
|
||||||
* is not NULL then error prints an error message using printf style
|
* is not NULL then error prints an error message using printf style
|
||||||
* formatting. It then raises the error exception.
|
* formatting. It then raises the error exception.
|
||||||
*/
|
*/
|
||||||
|
static void
|
||||||
#ifdef __STDC__
|
exverror(int cond, const char *msg, va_list ap)
|
||||||
void
|
|
||||||
error(char *msg, ...) {
|
|
||||||
#else
|
|
||||||
void
|
|
||||||
error(va_alist)
|
|
||||||
va_dcl
|
|
||||||
{
|
{
|
||||||
char *msg;
|
|
||||||
#endif
|
|
||||||
va_list ap;
|
|
||||||
|
|
||||||
CLEAR_PENDING_INT;
|
CLEAR_PENDING_INT;
|
||||||
INTOFF;
|
INTOFF;
|
||||||
#ifdef __STDC__
|
|
||||||
va_start(ap, msg);
|
|
||||||
#else
|
|
||||||
va_start(ap);
|
|
||||||
msg = va_arg(ap, char *);
|
|
||||||
#endif
|
|
||||||
#if DEBUG
|
#if DEBUG
|
||||||
if (msg)
|
if (msg)
|
||||||
TRACE(("error(\"%s\") pid=%d\n", msg, getpid()));
|
TRACE(("exverror(%d, \"%s\") pid=%d\n", cond, msg, getpid()));
|
||||||
else
|
else
|
||||||
TRACE(("error(NULL) pid=%d\n", getpid()));
|
TRACE(("exverror(%d, NULL) pid=%d\n", cond, getpid()));
|
||||||
#endif
|
#endif
|
||||||
if (msg) {
|
if (msg) {
|
||||||
if (commandname)
|
if (commandname)
|
||||||
|
@ -157,96 +156,30 @@ error(va_alist)
|
||||||
doformat(&errout, msg, ap);
|
doformat(&errout, msg, ap);
|
||||||
out2c('\n');
|
out2c('\n');
|
||||||
}
|
}
|
||||||
va_end(ap);
|
|
||||||
flushall();
|
flushall();
|
||||||
exraise(EXERROR);
|
exraise(cond);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#ifdef notdef /* These strange error messages only confuse. -- kjb */
|
void
|
||||||
/*
|
error(const char *msg, ...)
|
||||||
* Table of error messages.
|
{
|
||||||
*/
|
va_list ap;
|
||||||
|
va_start(ap, msg);
|
||||||
struct errname {
|
exverror(EXERROR, msg, ap);
|
||||||
short errcode; /* error number */
|
va_end(ap);
|
||||||
short action; /* operation which encountered the error */
|
}
|
||||||
char *msg; /* text describing the error */
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
#define ALL (E_OPEN|E_CREAT|E_EXEC)
|
void
|
||||||
|
exerror(int cond, const char *msg, ...)
|
||||||
STATIC const struct errname errormsg[] = {
|
{
|
||||||
EINTR, ALL, "interrupted",
|
va_list ap;
|
||||||
EACCES, ALL, "permission denied",
|
va_start(ap, msg);
|
||||||
EIO, ALL, "I/O error",
|
exverror(cond, msg, ap);
|
||||||
ENOENT, E_OPEN, "no such file",
|
va_end(ap);
|
||||||
ENOENT, E_CREAT, "directory nonexistent",
|
}
|
||||||
ENOENT, E_EXEC, "not found",
|
|
||||||
ENOTDIR, E_OPEN, "no such file",
|
|
||||||
ENOTDIR, E_CREAT, "directory nonexistent",
|
|
||||||
ENOTDIR, E_EXEC, "not found",
|
|
||||||
ENOEXEC, ALL, "not an executable",
|
|
||||||
EISDIR, ALL, "is a directory",
|
|
||||||
/* EMFILE, ALL, "too many open files", */
|
|
||||||
ENFILE, ALL, "file table overflow",
|
|
||||||
ENOSPC, ALL, "file system full",
|
|
||||||
#ifdef EDQUOT
|
|
||||||
EDQUOT, ALL, "disk quota exceeded",
|
|
||||||
#endif
|
|
||||||
#ifdef ENOSR
|
|
||||||
ENOSR, ALL, "no streams resources",
|
|
||||||
#endif
|
|
||||||
ENXIO, ALL, "no such device or address",
|
|
||||||
EROFS, ALL, "read-only file system",
|
|
||||||
ETXTBSY, ALL, "text busy",
|
|
||||||
#ifdef SYSV
|
|
||||||
EAGAIN, E_EXEC, "not enough memory",
|
|
||||||
#endif
|
|
||||||
ENOMEM, ALL, "not enough memory",
|
|
||||||
#ifdef ENOLINK
|
|
||||||
ENOLINK, ALL, "remote access failed",
|
|
||||||
#endif
|
|
||||||
#ifdef EMULTIHOP
|
|
||||||
EMULTIHOP, ALL, "remote access failed",
|
|
||||||
#endif
|
|
||||||
#ifdef ECOMM
|
|
||||||
ECOMM, ALL, "remote access failed",
|
|
||||||
#endif
|
|
||||||
#ifdef ESTALE
|
|
||||||
ESTALE, ALL, "remote access failed",
|
|
||||||
#endif
|
|
||||||
#ifdef ETIMEDOUT
|
|
||||||
ETIMEDOUT, ALL, "remote access failed",
|
|
||||||
#endif
|
|
||||||
#ifdef ELOOP
|
|
||||||
ELOOP, ALL, "symbolic link loop",
|
|
||||||
#endif
|
|
||||||
E2BIG, E_EXEC, "argument list too long",
|
|
||||||
#ifdef ELIBACC
|
|
||||||
ELIBACC, E_EXEC, "shared library missing",
|
|
||||||
#endif
|
|
||||||
0, 0, NULL
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Return a string describing an error. The returned string may be a
|
* $PchId: error.c,v 1.5 2006/04/10 14:36:23 philip Exp $
|
||||||
* pointer to a static buffer that will be overwritten on the next call.
|
|
||||||
* Action describes the operation that got the error.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
char *
|
|
||||||
errmsg(e, action) {
|
|
||||||
const struct errname *ep;
|
|
||||||
static char buf[12];
|
|
||||||
|
|
||||||
for (ep = errormsg ; ep->errcode ; ep++) {
|
|
||||||
if (ep->errcode == e && (ep->action & action) != 0)
|
|
||||||
return ep->msg;
|
|
||||||
}
|
|
||||||
fmtstr(buf, sizeof buf, "error %d", e);
|
|
||||||
return buf;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/*-
|
/*-
|
||||||
* Copyright (c) 1991 The Regents of the University of California.
|
* Copyright (c) 1991, 1993
|
||||||
* All rights reserved.
|
* The Regents of the University of California. All rights reserved.
|
||||||
*
|
*
|
||||||
* This code is derived from software contributed to Berkeley by
|
* This code is derived from software contributed to Berkeley by
|
||||||
* Kenneth Almquist.
|
* Kenneth Almquist.
|
||||||
|
@ -13,10 +13,6 @@
|
||||||
* 2. Redistributions in binary form must reproduce the above copyright
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
* notice, this list of conditions and the following disclaimer in the
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
* documentation and/or other materials provided with the distribution.
|
* documentation and/or other materials provided with the distribution.
|
||||||
* 3. All advertising materials mentioning features or use of this software
|
|
||||||
* must display the following acknowledgement:
|
|
||||||
* This product includes software developed by the University of
|
|
||||||
* California, Berkeley and its contributors.
|
|
||||||
* 4. Neither the name of the University nor the names of its contributors
|
* 4. Neither the name of the University nor the names of its contributors
|
||||||
* may be used to endorse or promote products derived from this software
|
* may be used to endorse or promote products derived from this software
|
||||||
* without specific prior written permission.
|
* without specific prior written permission.
|
||||||
|
@ -33,41 +29,35 @@
|
||||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||||
* SUCH DAMAGE.
|
* SUCH DAMAGE.
|
||||||
*
|
*
|
||||||
* @(#)error.h 5.1 (Berkeley) 3/7/91
|
* @(#)error.h 8.2 (Berkeley) 5/4/95
|
||||||
|
* $FreeBSD: src/bin/sh/error.h,v 1.17 2004/04/06 20:06:51 markm Exp $
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
|
||||||
* Types of operations (passed to the errmsg routine).
|
|
||||||
*/
|
|
||||||
|
|
||||||
#define E_OPEN 01 /* opening a file */
|
|
||||||
#define E_CREAT 02 /* creating a file */
|
|
||||||
#define E_EXEC 04 /* executing a program */
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* We enclose jmp_buf in a structure so that we can declare pointers to
|
* We enclose jmp_buf in a structure so that we can declare pointers to
|
||||||
* jump locations. The global variable handler contains the location to
|
* jump locations. The global variable handler contains the location to
|
||||||
* jump to when an exception occurs, and the global variable exception
|
* jump to when an exception occurs, and the global variable exception
|
||||||
* contains a code identifying the exeception. To implement nested
|
* contains a code identifying the exception. To implement nested
|
||||||
* exception handlers, the user should save the value of handler on entry
|
* exception handlers, the user should save the value of handler on entry
|
||||||
* to an inner scope, set handler to point to a jmploc structure for the
|
* to an inner scope, set handler to point to a jmploc structure for the
|
||||||
* inner scope, and restore handler on exit from the scope.
|
* inner scope, and restore handler on exit from the scope.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <setjmp.h>
|
#include <setjmp.h>
|
||||||
|
#include <signal.h>
|
||||||
|
|
||||||
struct jmploc {
|
struct jmploc {
|
||||||
jmp_buf loc;
|
jmp_buf loc;
|
||||||
};
|
};
|
||||||
|
|
||||||
extern struct jmploc *handler;
|
extern struct jmploc *handler;
|
||||||
extern int exception;
|
extern volatile sig_atomic_t exception;
|
||||||
|
|
||||||
/* exceptions */
|
/* exceptions */
|
||||||
#define EXINT 0 /* SIGINT received */
|
#define EXINT 0 /* SIGINT received */
|
||||||
#define EXERROR 1 /* a generic error */
|
#define EXERROR 1 /* a generic error */
|
||||||
#define EXSHELLPROC 2 /* execute a shell procedure */
|
#define EXSHELLPROC 2 /* execute a shell procedure */
|
||||||
|
#define EXEXEC 3 /* command execution failed */
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -77,32 +67,21 @@ extern int exception;
|
||||||
* more fun than worrying about efficiency and portability. :-))
|
* more fun than worrying about efficiency and portability. :-))
|
||||||
*/
|
*/
|
||||||
|
|
||||||
extern volatile int suppressint;
|
extern volatile sig_atomic_t suppressint;
|
||||||
extern volatile int intpending;
|
extern volatile sig_atomic_t intpending;
|
||||||
extern char *commandname; /* name of command--printed on error */
|
|
||||||
|
|
||||||
#define INTOFF suppressint++
|
#define INTOFF suppressint++
|
||||||
#define INTON if (--suppressint == 0 && intpending) onint(); else
|
#define INTON { if (--suppressint == 0 && intpending) onint(); }
|
||||||
#define FORCEINTON {suppressint = 0; if (intpending) onint();}
|
#define FORCEINTON {suppressint = 0; if (intpending) onint();}
|
||||||
#define CLEAR_PENDING_INT intpending = 0
|
#define CLEAR_PENDING_INT intpending = 0
|
||||||
#define int_pending() intpending
|
#define int_pending() intpending
|
||||||
|
|
||||||
#ifdef __STDC__
|
#define __printf0like(a,b)
|
||||||
|
|
||||||
void exraise(int);
|
void exraise(int);
|
||||||
void onint(void);
|
void onint(void);
|
||||||
void error2(char *, char *);
|
void error(const char *, ...) __printf0like(1, 2);
|
||||||
void error(char *, ...);
|
void exerror(int, const char *, ...) __printf0like(2, 3);
|
||||||
char *errmsg(int, int);
|
|
||||||
#else
|
|
||||||
void exraise();
|
|
||||||
void onint();
|
|
||||||
void error2();
|
|
||||||
void error();
|
|
||||||
char *errmsg();
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Errmsg uses confusingly different messages. Prefer strerror(). -- kjb */
|
|
||||||
#define errmsg(errno, action) strerror(errno)
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -111,6 +90,12 @@ char *errmsg();
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifdef BSD
|
#ifdef BSD
|
||||||
|
#ifndef __minix
|
||||||
#define setjmp(jmploc) _setjmp(jmploc)
|
#define setjmp(jmploc) _setjmp(jmploc)
|
||||||
#define longjmp(jmploc, val) _longjmp(jmploc, val)
|
#define longjmp(jmploc, val) _longjmp(jmploc, val)
|
||||||
#endif
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
* $PchId: error.h,v 1.5 2006/04/10 14:36:43 philip Exp $
|
||||||
|
*/
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/*-
|
/*-
|
||||||
* Copyright (c) 1991 The Regents of the University of California.
|
* Copyright (c) 1993
|
||||||
* All rights reserved.
|
* The Regents of the University of California. All rights reserved.
|
||||||
*
|
*
|
||||||
* This code is derived from software contributed to Berkeley by
|
* This code is derived from software contributed to Berkeley by
|
||||||
* Kenneth Almquist.
|
* Kenneth Almquist.
|
||||||
|
@ -13,10 +13,6 @@
|
||||||
* 2. Redistributions in binary form must reproduce the above copyright
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
* notice, this list of conditions and the following disclaimer in the
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
* documentation and/or other materials provided with the distribution.
|
* documentation and/or other materials provided with the distribution.
|
||||||
* 3. All advertising materials mentioning features or use of this software
|
|
||||||
* must display the following acknowledgement:
|
|
||||||
* This product includes software developed by the University of
|
|
||||||
* California, Berkeley and its contributors.
|
|
||||||
* 4. Neither the name of the University nor the names of its contributors
|
* 4. Neither the name of the University nor the names of its contributors
|
||||||
* may be used to endorse or promote products derived from this software
|
* may be used to endorse or promote products derived from this software
|
||||||
* without specific prior written permission.
|
* without specific prior written permission.
|
||||||
|
@ -35,8 +31,23 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef lint
|
#ifndef lint
|
||||||
static char sccsid[] = "@(#)eval.c 5.3 (Berkeley) 4/12/91";
|
#if 0
|
||||||
|
static char sccsid[] = "@(#)eval.c 8.9 (Berkeley) 6/8/95";
|
||||||
|
#endif
|
||||||
#endif /* not lint */
|
#endif /* not lint */
|
||||||
|
/*
|
||||||
|
#include <sys/cdefs.h>
|
||||||
|
__FBSDID("$FreeBSD: src/bin/sh/eval.c,v 1.42 2004/04/06 20:06:51 markm Exp $");
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef NO_PATHS_H
|
||||||
|
#include <paths.h>
|
||||||
|
#endif
|
||||||
|
#include <signal.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <sys/wait.h> /* For WIFSIGNALED(status) */
|
||||||
|
#include <errno.h>
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Evaluate a command.
|
* Evaluate a command.
|
||||||
|
@ -59,22 +70,21 @@ static char sccsid[] = "@(#)eval.c 5.3 (Berkeley) 4/12/91";
|
||||||
#include "var.h"
|
#include "var.h"
|
||||||
#include "memalloc.h"
|
#include "memalloc.h"
|
||||||
#include "error.h"
|
#include "error.h"
|
||||||
|
#include "show.h"
|
||||||
#include "mystring.h"
|
#include "mystring.h"
|
||||||
#include <sys/types.h>
|
#if !defined(NO_HISTORY) && !defined(EDITLINE)
|
||||||
#include <signal.h>
|
#include "myhistedit.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef _PATH_STDPATH
|
||||||
|
#define _PATH_STDPATH "/usr/bin:/bin:/usr/sbin:/sbin:"
|
||||||
|
#endif
|
||||||
|
|
||||||
/* flags in argument to evaltree */
|
/* flags in argument to evaltree */
|
||||||
#define EV_EXIT 01 /* exit after evaluating tree */
|
#define EV_EXIT 01 /* exit after evaluating tree */
|
||||||
#define EV_TESTED 02 /* exit status is checked; ignore -e flag */
|
#define EV_TESTED 02 /* exit status is checked; ignore -e flag */
|
||||||
#define EV_BACKCMD 04 /* command executing within back quotes */
|
#define EV_BACKCMD 04 /* command executing within back quotes */
|
||||||
|
|
||||||
|
|
||||||
/* reasons for skipping commands (see comment on breakcmd routine) */
|
|
||||||
#define SKIPBREAK 1
|
|
||||||
#define SKIPCONT 2
|
|
||||||
#define SKIPFUNC 3
|
|
||||||
|
|
||||||
MKINIT int evalskip; /* set if we are skipping commands */
|
MKINIT int evalskip; /* set if we are skipping commands */
|
||||||
STATIC int skipcount; /* number of levels to skip */
|
STATIC int skipcount; /* number of levels to skip */
|
||||||
MKINIT int loopnest; /* current loop nesting level */
|
MKINIT int loopnest; /* current loop nesting level */
|
||||||
|
@ -87,7 +97,6 @@ int exitstatus; /* exit status of last command */
|
||||||
int oexitstatus; /* saved exit status */
|
int oexitstatus; /* saved exit status */
|
||||||
|
|
||||||
|
|
||||||
#ifdef __STDC__
|
|
||||||
STATIC void evalloop(union node *);
|
STATIC void evalloop(union node *);
|
||||||
STATIC void evalfor(union node *);
|
STATIC void evalfor(union node *);
|
||||||
STATIC void evalcase(union node *, int);
|
STATIC void evalcase(union node *, int);
|
||||||
|
@ -96,17 +105,6 @@ STATIC void expredir(union node *);
|
||||||
STATIC void evalpipe(union node *);
|
STATIC void evalpipe(union node *);
|
||||||
STATIC void evalcommand(union node *, int, struct backcmd *);
|
STATIC void evalcommand(union node *, int, struct backcmd *);
|
||||||
STATIC void prehash(union node *);
|
STATIC void prehash(union node *);
|
||||||
#else
|
|
||||||
STATIC void evalloop();
|
|
||||||
STATIC void evalfor();
|
|
||||||
STATIC void evalcase();
|
|
||||||
STATIC void evalsubshell();
|
|
||||||
STATIC void expredir();
|
|
||||||
STATIC void evalpipe();
|
|
||||||
STATIC void evalcommand();
|
|
||||||
STATIC void prehash();
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -130,11 +128,11 @@ SHELLPROC {
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The eval commmand.
|
* The eval command.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
evalcmd(argc, argv)
|
int
|
||||||
char **argv;
|
evalcmd(int argc, char **argv)
|
||||||
{
|
{
|
||||||
char *p;
|
char *p;
|
||||||
char *concat;
|
char *concat;
|
||||||
|
@ -166,8 +164,7 @@ evalcmd(argc, argv)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void
|
void
|
||||||
evalstring(s)
|
evalstring(char *s)
|
||||||
char *s;
|
|
||||||
{
|
{
|
||||||
union node *n;
|
union node *n;
|
||||||
struct stackmark smark;
|
struct stackmark smark;
|
||||||
|
@ -190,14 +187,17 @@ evalstring(s)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void
|
void
|
||||||
evaltree(n, flags)
|
evaltree(union node *n, int flags)
|
||||||
union node *n;
|
|
||||||
{
|
{
|
||||||
if (n == NULL) {
|
if (n == NULL) {
|
||||||
TRACE(("evaltree(NULL) called\n"));
|
TRACE(("evaltree(NULL) called\n"));
|
||||||
return;
|
exitstatus = 0;
|
||||||
|
goto out;
|
||||||
}
|
}
|
||||||
TRACE(("evaltree(0x%x: %d) called\n", (int)n, n->type));
|
#if !defined(NO_HISTORY) && !defined(EDITLINE)
|
||||||
|
displayhist = 1; /* show history substitutions done with fc */
|
||||||
|
#endif
|
||||||
|
TRACE(("evaltree(0x%lx: %d) called\n", (long)n, n->type));
|
||||||
switch (n->type) {
|
switch (n->type) {
|
||||||
case NSEMI:
|
case NSEMI:
|
||||||
evaltree(n->nbinary.ch1, 0);
|
evaltree(n->nbinary.ch1, 0);
|
||||||
|
@ -207,8 +207,9 @@ evaltree(n, flags)
|
||||||
break;
|
break;
|
||||||
case NAND:
|
case NAND:
|
||||||
evaltree(n->nbinary.ch1, EV_TESTED);
|
evaltree(n->nbinary.ch1, EV_TESTED);
|
||||||
if (evalskip || exitstatus != 0)
|
if (evalskip || exitstatus != 0) {
|
||||||
goto out;
|
goto out;
|
||||||
|
}
|
||||||
evaltree(n->nbinary.ch2, flags);
|
evaltree(n->nbinary.ch2, flags);
|
||||||
break;
|
break;
|
||||||
case NOR:
|
case NOR:
|
||||||
|
@ -230,19 +231,15 @@ evaltree(n, flags)
|
||||||
evalsubshell(n, flags);
|
evalsubshell(n, flags);
|
||||||
break;
|
break;
|
||||||
case NIF: {
|
case NIF: {
|
||||||
int status = 0;
|
|
||||||
|
|
||||||
evaltree(n->nif.test, EV_TESTED);
|
evaltree(n->nif.test, EV_TESTED);
|
||||||
if (evalskip)
|
if (evalskip)
|
||||||
goto out;
|
goto out;
|
||||||
if (exitstatus == 0) {
|
if (exitstatus == 0)
|
||||||
evaltree(n->nif.ifpart, flags);
|
evaltree(n->nif.ifpart, flags);
|
||||||
status = exitstatus;
|
else if (n->nif.elsepart)
|
||||||
} else if (n->nif.elsepart) {
|
|
||||||
evaltree(n->nif.elsepart, flags);
|
evaltree(n->nif.elsepart, flags);
|
||||||
status = exitstatus;
|
else
|
||||||
}
|
exitstatus = 0;
|
||||||
exitstatus = status;
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case NWHILE:
|
case NWHILE:
|
||||||
|
@ -259,6 +256,11 @@ evaltree(n, flags)
|
||||||
defun(n->narg.text, n->narg.next);
|
defun(n->narg.text, n->narg.next);
|
||||||
exitstatus = 0;
|
exitstatus = 0;
|
||||||
break;
|
break;
|
||||||
|
case NNOT:
|
||||||
|
evaltree(n->nnot.com, EV_TESTED);
|
||||||
|
exitstatus = !exitstatus;
|
||||||
|
break;
|
||||||
|
|
||||||
case NPIPE:
|
case NPIPE:
|
||||||
evalpipe(n);
|
evalpipe(n);
|
||||||
break;
|
break;
|
||||||
|
@ -275,15 +277,13 @@ out:
|
||||||
dotrap();
|
dotrap();
|
||||||
if ((flags & EV_EXIT) || (eflag && exitstatus
|
if ((flags & EV_EXIT) || (eflag && exitstatus
|
||||||
&& !(flags & EV_TESTED) && (n->type == NCMD ||
|
&& !(flags & EV_TESTED) && (n->type == NCMD ||
|
||||||
n->type == NSUBSHELL))) {
|
n->type == NSUBSHELL)))
|
||||||
exitshell(exitstatus);
|
exitshell(exitstatus);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
STATIC void
|
STATIC void
|
||||||
evalloop(n)
|
evalloop(union node *n)
|
||||||
union node *n;
|
|
||||||
{
|
{
|
||||||
int status;
|
int status;
|
||||||
|
|
||||||
|
@ -319,8 +319,7 @@ skipping: if (evalskip == SKIPCONT && --skipcount <= 0) {
|
||||||
|
|
||||||
|
|
||||||
STATIC void
|
STATIC void
|
||||||
evalfor(n)
|
evalfor(union node *n)
|
||||||
union node *n;
|
|
||||||
{
|
{
|
||||||
struct arglist arglist;
|
struct arglist arglist;
|
||||||
union node *argp;
|
union node *argp;
|
||||||
|
@ -331,7 +330,7 @@ evalfor(n)
|
||||||
arglist.lastp = &arglist.list;
|
arglist.lastp = &arglist.list;
|
||||||
for (argp = n->nfor.args ; argp ; argp = argp->narg.next) {
|
for (argp = n->nfor.args ; argp ; argp = argp->narg.next) {
|
||||||
oexitstatus = exitstatus;
|
oexitstatus = exitstatus;
|
||||||
expandarg(argp, &arglist, 1);
|
expandarg(argp, &arglist, EXP_FULL | EXP_TILDE);
|
||||||
if (evalskip)
|
if (evalskip)
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
@ -360,8 +359,7 @@ out:
|
||||||
|
|
||||||
|
|
||||||
STATIC void
|
STATIC void
|
||||||
evalcase(n, flags)
|
evalcase(union node *n, int flags)
|
||||||
union node *n;
|
|
||||||
{
|
{
|
||||||
union node *cp;
|
union node *cp;
|
||||||
union node *patp;
|
union node *patp;
|
||||||
|
@ -371,7 +369,7 @@ evalcase(n, flags)
|
||||||
setstackmark(&smark);
|
setstackmark(&smark);
|
||||||
arglist.lastp = &arglist.list;
|
arglist.lastp = &arglist.list;
|
||||||
oexitstatus = exitstatus;
|
oexitstatus = exitstatus;
|
||||||
expandarg(n->ncase.expr, &arglist, 0);
|
expandarg(n->ncase.expr, &arglist, EXP_TILDE);
|
||||||
for (cp = n->ncase.cases ; cp && evalskip == 0 ; cp = cp->nclist.next) {
|
for (cp = n->ncase.cases ; cp && evalskip == 0 ; cp = cp->nclist.next) {
|
||||||
for (patp = cp->nclist.pattern ; patp ; patp = patp->narg.next) {
|
for (patp = cp->nclist.pattern ; patp ; patp = patp->narg.next) {
|
||||||
if (casematch(patp, arglist.list->text)) {
|
if (casematch(patp, arglist.list->text)) {
|
||||||
|
@ -393,8 +391,7 @@ out:
|
||||||
*/
|
*/
|
||||||
|
|
||||||
STATIC void
|
STATIC void
|
||||||
evalsubshell(n, flags)
|
evalsubshell(union node *n, int flags)
|
||||||
union node *n;
|
|
||||||
{
|
{
|
||||||
struct job *jp;
|
struct job *jp;
|
||||||
int backgnd = (n->type == NBACKGND);
|
int backgnd = (n->type == NBACKGND);
|
||||||
|
@ -409,7 +406,7 @@ evalsubshell(n, flags)
|
||||||
}
|
}
|
||||||
if (! backgnd) {
|
if (! backgnd) {
|
||||||
INTOFF;
|
INTOFF;
|
||||||
exitstatus = waitforjob(jp);
|
exitstatus = waitforjob(jp, (int *)NULL);
|
||||||
INTON;
|
INTON;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -421,20 +418,30 @@ evalsubshell(n, flags)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
STATIC void
|
STATIC void
|
||||||
expredir(n)
|
expredir(union node *n)
|
||||||
union node *n;
|
|
||||||
{
|
{
|
||||||
register union node *redir;
|
union node *redir;
|
||||||
|
|
||||||
for (redir = n ; redir ; redir = redir->nfile.next) {
|
for (redir = n ; redir ; redir = redir->nfile.next) {
|
||||||
oexitstatus = exitstatus;
|
|
||||||
if (redir->type == NFROM
|
|
||||||
|| redir->type == NTO
|
|
||||||
|| redir->type == NAPPEND) {
|
|
||||||
struct arglist fn;
|
struct arglist fn;
|
||||||
fn.lastp = &fn.list;
|
fn.lastp = &fn.list;
|
||||||
expandarg(redir->nfile.fname, &fn, 0);
|
oexitstatus = exitstatus;
|
||||||
|
switch (redir->type) {
|
||||||
|
case NFROM:
|
||||||
|
case NTO:
|
||||||
|
case NFROMTO:
|
||||||
|
case NAPPEND:
|
||||||
|
case NCLOBBER:
|
||||||
|
expandarg(redir->nfile.fname, &fn, EXP_TILDE | EXP_REDIR);
|
||||||
redir->nfile.expfname = fn.list->text;
|
redir->nfile.expfname = fn.list->text;
|
||||||
|
break;
|
||||||
|
case NFROMFD:
|
||||||
|
case NTOFD:
|
||||||
|
if (redir->ndup.vname) {
|
||||||
|
expandarg(redir->ndup.vname, &fn, EXP_FULL | EXP_TILDE);
|
||||||
|
fixredir(redir, fn.list->text, 1);
|
||||||
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -449,8 +456,7 @@ expredir(n)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
STATIC void
|
STATIC void
|
||||||
evalpipe(n)
|
evalpipe(union node *n)
|
||||||
union node *n;
|
|
||||||
{
|
{
|
||||||
struct job *jp;
|
struct job *jp;
|
||||||
struct nodelist *lp;
|
struct nodelist *lp;
|
||||||
|
@ -458,7 +464,7 @@ evalpipe(n)
|
||||||
int prevfd;
|
int prevfd;
|
||||||
int pip[2];
|
int pip[2];
|
||||||
|
|
||||||
TRACE(("evalpipe(0x%x) called\n", (int)n));
|
TRACE(("evalpipe(0x%lx) called\n", (long)n));
|
||||||
pipelen = 0;
|
pipelen = 0;
|
||||||
for (lp = n->npipe.cmdlist ; lp ; lp = lp->next)
|
for (lp = n->npipe.cmdlist ; lp ; lp = lp->next)
|
||||||
pipelen++;
|
pipelen++;
|
||||||
|
@ -471,21 +477,20 @@ evalpipe(n)
|
||||||
if (lp->next) {
|
if (lp->next) {
|
||||||
if (pipe(pip) < 0) {
|
if (pipe(pip) < 0) {
|
||||||
close(prevfd);
|
close(prevfd);
|
||||||
error("Pipe call failed");
|
error("Pipe call failed: %s", strerror(errno));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (forkshell(jp, lp->n, n->npipe.backgnd) == 0) {
|
if (forkshell(jp, lp->n, n->npipe.backgnd) == 0) {
|
||||||
INTON;
|
INTON;
|
||||||
if (prevfd > 0) {
|
if (prevfd > 0) {
|
||||||
close(0);
|
dup2(prevfd, 0);
|
||||||
copyfd(prevfd, 0);
|
|
||||||
close(prevfd);
|
close(prevfd);
|
||||||
}
|
}
|
||||||
if (pip[1] >= 0) {
|
if (pip[1] >= 0) {
|
||||||
|
if (!(prevfd >= 0 && pip[0] == 0))
|
||||||
close(pip[0]);
|
close(pip[0]);
|
||||||
if (pip[1] != 1) {
|
if (pip[1] != 1) {
|
||||||
close(1);
|
dup2(pip[1], 1);
|
||||||
copyfd(pip[1], 1);
|
|
||||||
close(pip[1]);
|
close(pip[1]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -499,7 +504,7 @@ evalpipe(n)
|
||||||
INTON;
|
INTON;
|
||||||
if (n->npipe.backgnd == 0) {
|
if (n->npipe.backgnd == 0) {
|
||||||
INTOFF;
|
INTOFF;
|
||||||
exitstatus = waitforjob(jp);
|
exitstatus = waitforjob(jp, (int *)NULL);
|
||||||
TRACE(("evalpipe: job done exit status %d\n", exitstatus));
|
TRACE(("evalpipe: job done exit status %d\n", exitstatus));
|
||||||
INTON;
|
INTON;
|
||||||
}
|
}
|
||||||
|
@ -515,9 +520,7 @@ evalpipe(n)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void
|
void
|
||||||
evalbackcmd(n, result)
|
evalbackcmd(union node *n, struct backcmd *result)
|
||||||
union node *n;
|
|
||||||
struct backcmd *result;
|
|
||||||
{
|
{
|
||||||
int pip[2];
|
int pip[2];
|
||||||
struct job *jp;
|
struct job *jp;
|
||||||
|
@ -529,21 +532,22 @@ evalbackcmd(n, result)
|
||||||
result->nleft = 0;
|
result->nleft = 0;
|
||||||
result->jp = NULL;
|
result->jp = NULL;
|
||||||
if (n == NULL) {
|
if (n == NULL) {
|
||||||
/* `` */
|
exitstatus = 0;
|
||||||
} else
|
goto out;
|
||||||
|
}
|
||||||
if (n->type == NCMD) {
|
if (n->type == NCMD) {
|
||||||
exitstatus = oexitstatus;
|
exitstatus = oexitstatus;
|
||||||
evalcommand(n, EV_BACKCMD, result);
|
evalcommand(n, EV_BACKCMD, result);
|
||||||
} else {
|
} else {
|
||||||
|
exitstatus = 0;
|
||||||
if (pipe(pip) < 0)
|
if (pipe(pip) < 0)
|
||||||
error("Pipe call failed");
|
error("Pipe call failed: %s", strerror(errno));
|
||||||
jp = makejob(n, 1);
|
jp = makejob(n, 1);
|
||||||
if (forkshell(jp, n, FORK_NOJOB) == 0) {
|
if (forkshell(jp, n, FORK_NOJOB) == 0) {
|
||||||
FORCEINTON;
|
FORCEINTON;
|
||||||
close(pip[0]);
|
close(pip[0]);
|
||||||
if (pip[1] != 1) {
|
if (pip[1] != 1) {
|
||||||
close(1);
|
dup2(pip[1], 1);
|
||||||
copyfd(pip[1], 1);
|
|
||||||
close(pip[1]);
|
close(pip[1]);
|
||||||
}
|
}
|
||||||
evaltree(n, EV_EXIT);
|
evaltree(n, EV_EXIT);
|
||||||
|
@ -552,8 +556,9 @@ evalbackcmd(n, result)
|
||||||
result->fd = pip[0];
|
result->fd = pip[0];
|
||||||
result->jp = jp;
|
result->jp = jp;
|
||||||
}
|
}
|
||||||
|
out:
|
||||||
popstackmark(&smark);
|
popstackmark(&smark);
|
||||||
TRACE(("evalbackcmd done: fd=%d buf=0x%x nleft=%d jp=0x%x\n",
|
TRACE(("evalbackcmd done: fd=%d buf=%p nleft=%d jp=%p\n",
|
||||||
result->fd, result->buf, result->nleft, result->jp));
|
result->fd, result->buf, result->nleft, result->jp));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -564,9 +569,7 @@ evalbackcmd(n, result)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
STATIC void
|
STATIC void
|
||||||
evalcommand(cmd, flags, backcmd)
|
evalcommand(union node *cmd, int flags, struct backcmd *backcmd)
|
||||||
union node *cmd;
|
|
||||||
struct backcmd *backcmd;
|
|
||||||
{
|
{
|
||||||
struct stackmark smark;
|
struct stackmark smark;
|
||||||
union node *argp;
|
union node *argp;
|
||||||
|
@ -577,7 +580,6 @@ evalcommand(cmd, flags, backcmd)
|
||||||
char **envp;
|
char **envp;
|
||||||
int varflag;
|
int varflag;
|
||||||
struct strlist *sp;
|
struct strlist *sp;
|
||||||
register char *p;
|
|
||||||
int mode;
|
int mode;
|
||||||
int pip[2];
|
int pip[2];
|
||||||
struct cmdentry cmdentry;
|
struct cmdentry cmdentry;
|
||||||
|
@ -589,27 +591,38 @@ evalcommand(cmd, flags, backcmd)
|
||||||
struct localvar *volatile savelocalvars;
|
struct localvar *volatile savelocalvars;
|
||||||
volatile int e;
|
volatile int e;
|
||||||
char *lastarg;
|
char *lastarg;
|
||||||
|
int realstatus;
|
||||||
|
int do_clearcmdentry;
|
||||||
|
#if __GNUC__
|
||||||
|
/* Avoid longjmp clobbering */
|
||||||
|
(void) &argv;
|
||||||
|
(void) &argc;
|
||||||
|
(void) &lastarg;
|
||||||
|
(void) &flags;
|
||||||
|
(void) &do_clearcmdentry;
|
||||||
|
#endif
|
||||||
|
|
||||||
/* First expand the arguments. */
|
/* First expand the arguments. */
|
||||||
TRACE(("evalcommand(0x%x, %d) called\n", (int)cmd, flags));
|
TRACE(("evalcommand(0x%lx, %d) called\n", (long)cmd, flags));
|
||||||
setstackmark(&smark);
|
setstackmark(&smark);
|
||||||
arglist.lastp = &arglist.list;
|
arglist.lastp = &arglist.list;
|
||||||
varlist.lastp = &varlist.list;
|
varlist.lastp = &varlist.list;
|
||||||
varflag = 1;
|
varflag = 1;
|
||||||
|
do_clearcmdentry = 0;
|
||||||
oexitstatus = exitstatus;
|
oexitstatus = exitstatus;
|
||||||
exitstatus = 0;
|
exitstatus = 0;
|
||||||
for (argp = cmd->ncmd.args ; argp ; argp = argp->narg.next) {
|
for (argp = cmd->ncmd.args ; argp ; argp = argp->narg.next) {
|
||||||
p = argp->narg.text;
|
char *p = argp->narg.text;
|
||||||
if (varflag && is_name(*p)) {
|
if (varflag && is_name(*p)) {
|
||||||
do {
|
do {
|
||||||
p++;
|
p++;
|
||||||
} while (is_in_name(*p));
|
} while (is_in_name(*p));
|
||||||
if (*p == '=') {
|
if (*p == '=') {
|
||||||
expandarg(argp, &varlist, 0);
|
expandarg(argp, &varlist, EXP_VARTILDE);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
expandarg(argp, &arglist, 1);
|
expandarg(argp, &arglist, EXP_FULL | EXP_TILDE);
|
||||||
varflag = 0;
|
varflag = 0;
|
||||||
}
|
}
|
||||||
*arglist.lastp = NULL;
|
*arglist.lastp = NULL;
|
||||||
|
@ -619,8 +632,11 @@ evalcommand(cmd, flags, backcmd)
|
||||||
for (sp = arglist.list ; sp ; sp = sp->next)
|
for (sp = arglist.list ; sp ; sp = sp->next)
|
||||||
argc++;
|
argc++;
|
||||||
argv = stalloc(sizeof (char *) * (argc + 1));
|
argv = stalloc(sizeof (char *) * (argc + 1));
|
||||||
for (sp = arglist.list ; sp ; sp = sp->next)
|
|
||||||
|
for (sp = arglist.list ; sp ; sp = sp->next) {
|
||||||
|
TRACE(("evalcommand arg: %s\n", sp->text));
|
||||||
*argv++ = sp->text;
|
*argv++ = sp->text;
|
||||||
|
}
|
||||||
*argv = NULL;
|
*argv = NULL;
|
||||||
lastarg = NULL;
|
lastarg = NULL;
|
||||||
if (iflag && funcnest == 0 && argc > 0)
|
if (iflag && funcnest == 0 && argc > 0)
|
||||||
|
@ -628,7 +644,7 @@ evalcommand(cmd, flags, backcmd)
|
||||||
argv -= argc;
|
argv -= argc;
|
||||||
|
|
||||||
/* Print the command if xflag is set. */
|
/* Print the command if xflag is set. */
|
||||||
if (xflag == 1) {
|
if (xflag) {
|
||||||
outc('+', &errout);
|
outc('+', &errout);
|
||||||
for (sp = varlist.list ; sp ; sp = sp->next) {
|
for (sp = varlist.list ; sp ; sp = sp->next) {
|
||||||
outc(' ', &errout);
|
outc(' ', &errout);
|
||||||
|
@ -647,11 +663,42 @@ evalcommand(cmd, flags, backcmd)
|
||||||
cmdentry.cmdtype = CMDBUILTIN;
|
cmdentry.cmdtype = CMDBUILTIN;
|
||||||
cmdentry.u.index = BLTINCMD;
|
cmdentry.u.index = BLTINCMD;
|
||||||
} else {
|
} else {
|
||||||
find_command(argv[0], &cmdentry, 1);
|
static const char PATH[] = "PATH=";
|
||||||
|
char *path = pathval();
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Modify the command lookup path, if a PATH= assignment
|
||||||
|
* is present
|
||||||
|
*/
|
||||||
|
for (sp = varlist.list ; sp ; sp = sp->next)
|
||||||
|
if (strncmp(sp->text, PATH, sizeof(PATH) - 1) == 0) {
|
||||||
|
path = sp->text + sizeof(PATH) - 1;
|
||||||
|
/*
|
||||||
|
* On `PATH=... command`, we need to make
|
||||||
|
* sure that the command isn't using the
|
||||||
|
* non-updated hash table of the outer PATH
|
||||||
|
* setting and we need to make sure that
|
||||||
|
* the hash table isn't filled with items
|
||||||
|
* from the temporary setting.
|
||||||
|
*
|
||||||
|
* It would be better to forbit using and
|
||||||
|
* updating the table while this command
|
||||||
|
* runs, by the command finding mechanism
|
||||||
|
* is heavily integrated with hash handling,
|
||||||
|
* so we just delete the hash before and after
|
||||||
|
* the command runs. Partly deleting like
|
||||||
|
* changepatch() does doesn't seem worth the
|
||||||
|
* bookinging effort, since most such runs add
|
||||||
|
* directories in front of the new PATH.
|
||||||
|
*/
|
||||||
|
clearcmdentry(0);
|
||||||
|
do_clearcmdentry = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
find_command(argv[0], &cmdentry, 1, path);
|
||||||
if (cmdentry.cmdtype == CMDUNKNOWN) { /* command not found */
|
if (cmdentry.cmdtype == CMDUNKNOWN) { /* command not found */
|
||||||
exitstatus = 2;
|
exitstatus = 127;
|
||||||
flushout(&errout);
|
flushout(&errout);
|
||||||
popstackmark(&smark);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
/* implement the bltin builtin here */
|
/* implement the bltin builtin here */
|
||||||
|
@ -662,9 +709,8 @@ evalcommand(cmd, flags, backcmd)
|
||||||
break;
|
break;
|
||||||
if ((cmdentry.u.index = find_builtin(*argv)) < 0) {
|
if ((cmdentry.u.index = find_builtin(*argv)) < 0) {
|
||||||
outfmt(&errout, "%s: not found\n", *argv);
|
outfmt(&errout, "%s: not found\n", *argv);
|
||||||
exitstatus = 2;
|
exitstatus = 127;
|
||||||
flushout(&errout);
|
flushout(&errout);
|
||||||
popstackmark(&smark);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (cmdentry.u.index != BLTINCMD)
|
if (cmdentry.u.index != BLTINCMD)
|
||||||
|
@ -675,17 +721,21 @@ evalcommand(cmd, flags, backcmd)
|
||||||
|
|
||||||
/* Fork off a child process if necessary. */
|
/* Fork off a child process if necessary. */
|
||||||
if (cmd->ncmd.backgnd
|
if (cmd->ncmd.backgnd
|
||||||
|| cmdentry.cmdtype == CMDNORMAL && (flags & EV_EXIT) == 0
|
|| (cmdentry.cmdtype == CMDNORMAL
|
||||||
|| (flags & EV_BACKCMD) != 0
|
&& ((flags & EV_EXIT) == 0 || Tflag))
|
||||||
|
|| ((flags & EV_BACKCMD) != 0
|
||||||
&& (cmdentry.cmdtype != CMDBUILTIN
|
&& (cmdentry.cmdtype != CMDBUILTIN
|
||||||
|
|| cmdentry.u.index == CDCMD
|
||||||
|| cmdentry.u.index == DOTCMD
|
|| cmdentry.u.index == DOTCMD
|
||||||
|| cmdentry.u.index == EVALCMD)) {
|
|| cmdentry.u.index == EVALCMD))
|
||||||
|
|| (cmdentry.cmdtype == CMDBUILTIN &&
|
||||||
|
cmdentry.u.index == COMMANDCMD)) {
|
||||||
jp = makejob(cmd, 1);
|
jp = makejob(cmd, 1);
|
||||||
mode = cmd->ncmd.backgnd;
|
mode = cmd->ncmd.backgnd;
|
||||||
if (flags & EV_BACKCMD) {
|
if (flags & EV_BACKCMD) {
|
||||||
mode = FORK_NOJOB;
|
mode = FORK_NOJOB;
|
||||||
if (pipe(pip) < 0)
|
if (pipe(pip) < 0)
|
||||||
error("Pipe call failed");
|
error("Pipe call failed: %s", strerror(errno));
|
||||||
}
|
}
|
||||||
if (forkshell(jp, cmd, mode) != 0)
|
if (forkshell(jp, cmd, mode) != 0)
|
||||||
goto parent; /* at end of routine */
|
goto parent; /* at end of routine */
|
||||||
|
@ -693,8 +743,7 @@ evalcommand(cmd, flags, backcmd)
|
||||||
FORCEINTON;
|
FORCEINTON;
|
||||||
close(pip[0]);
|
close(pip[0]);
|
||||||
if (pip[1] != 1) {
|
if (pip[1] != 1) {
|
||||||
close(1);
|
dup2(pip[1], 1);
|
||||||
copyfd(pip[1], 1);
|
|
||||||
close(pip[1]);
|
close(pip[1]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -704,10 +753,13 @@ evalcommand(cmd, flags, backcmd)
|
||||||
/* This is the child process if a fork occurred. */
|
/* This is the child process if a fork occurred. */
|
||||||
/* Execute the command. */
|
/* Execute the command. */
|
||||||
if (cmdentry.cmdtype == CMDFUNCTION) {
|
if (cmdentry.cmdtype == CMDFUNCTION) {
|
||||||
|
#if DEBUG
|
||||||
trputs("Shell function: "); trargs(argv);
|
trputs("Shell function: "); trargs(argv);
|
||||||
|
#endif
|
||||||
redirect(cmd->ncmd.redirect, REDIR_PUSH);
|
redirect(cmd->ncmd.redirect, REDIR_PUSH);
|
||||||
saveparam = shellparam;
|
saveparam = shellparam;
|
||||||
shellparam.malloc = 0;
|
shellparam.malloc = 0;
|
||||||
|
shellparam.reset = 1;
|
||||||
shellparam.nparam = argc - 1;
|
shellparam.nparam = argc - 1;
|
||||||
shellparam.p = argv + 1;
|
shellparam.p = argv + 1;
|
||||||
shellparam.optnext = NULL;
|
shellparam.optnext = NULL;
|
||||||
|
@ -752,7 +804,9 @@ evalcommand(cmd, flags, backcmd)
|
||||||
if (flags & EV_EXIT)
|
if (flags & EV_EXIT)
|
||||||
exitshell(exitstatus);
|
exitshell(exitstatus);
|
||||||
} else if (cmdentry.cmdtype == CMDBUILTIN) {
|
} else if (cmdentry.cmdtype == CMDBUILTIN) {
|
||||||
|
#if DEBUG
|
||||||
trputs("builtin command: "); trargs(argv);
|
trputs("builtin command: "); trargs(argv);
|
||||||
|
#endif
|
||||||
mode = (cmdentry.u.index == EXECCMD)? 0 : REDIR_PUSH;
|
mode = (cmdentry.u.index == EXECCMD)? 0 : REDIR_PUSH;
|
||||||
if (flags == EV_BACKCMD) {
|
if (flags == EV_BACKCMD) {
|
||||||
memout.nleft = 0;
|
memout.nleft = 0;
|
||||||
|
@ -777,6 +831,7 @@ evalcommand(cmd, flags, backcmd)
|
||||||
exitstatus = (*builtinfunc[cmdentry.u.index])(argc, argv);
|
exitstatus = (*builtinfunc[cmdentry.u.index])(argc, argv);
|
||||||
flushall();
|
flushall();
|
||||||
cmddone:
|
cmddone:
|
||||||
|
cmdenviron = NULL;
|
||||||
out1 = &output;
|
out1 = &output;
|
||||||
out2 = &errout;
|
out2 = &errout;
|
||||||
freestdout();
|
freestdout();
|
||||||
|
@ -788,10 +843,15 @@ cmddone:
|
||||||
}
|
}
|
||||||
handler = savehandler;
|
handler = savehandler;
|
||||||
if (e != -1) {
|
if (e != -1) {
|
||||||
if (e != EXERROR || cmdentry.u.index == BLTINCMD
|
if ((e != EXERROR && e != EXEXEC)
|
||||||
|
|| cmdentry.u.index == BLTINCMD
|
||||||
|| cmdentry.u.index == DOTCMD
|
|| cmdentry.u.index == DOTCMD
|
||||||
|| cmdentry.u.index == EVALCMD
|
|| cmdentry.u.index == EVALCMD
|
||||||
|| cmdentry.u.index == EXECCMD)
|
#ifndef NO_HISTORY
|
||||||
|
|| cmdentry.u.index == HISTCMD
|
||||||
|
#endif
|
||||||
|
|| cmdentry.u.index == EXECCMD
|
||||||
|
|| cmdentry.u.index == COMMANDCMD)
|
||||||
exraise(e);
|
exraise(e);
|
||||||
FORCEINTON;
|
FORCEINTON;
|
||||||
}
|
}
|
||||||
|
@ -803,19 +863,15 @@ cmddone:
|
||||||
memout.buf = NULL;
|
memout.buf = NULL;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
#if DEBUG
|
||||||
trputs("normal command: "); trargs(argv);
|
trputs("normal command: "); trargs(argv);
|
||||||
|
#endif
|
||||||
clearredir();
|
clearredir();
|
||||||
redirect(cmd->ncmd.redirect, 0);
|
redirect(cmd->ncmd.redirect, 0);
|
||||||
if (varlist.list) {
|
|
||||||
p = stalloc(strlen(pathval()) + 1);
|
|
||||||
scopy(pathval(), p);
|
|
||||||
} else {
|
|
||||||
p = pathval();
|
|
||||||
}
|
|
||||||
for (sp = varlist.list ; sp ; sp = sp->next)
|
for (sp = varlist.list ; sp ; sp = sp->next)
|
||||||
setvareq(sp->text, VEXPORT|VSTACK);
|
setvareq(sp->text, VEXPORT|VSTACK);
|
||||||
envp = environment();
|
envp = environment();
|
||||||
shellexec(argv, envp, p, cmdentry.u.index);
|
shellexec(argv, envp, pathval(), cmdentry.u.index);
|
||||||
/*NOTREACHED*/
|
/*NOTREACHED*/
|
||||||
}
|
}
|
||||||
goto out;
|
goto out;
|
||||||
|
@ -823,8 +879,12 @@ cmddone:
|
||||||
parent: /* parent process gets here (if we forked) */
|
parent: /* parent process gets here (if we forked) */
|
||||||
if (mode == 0) { /* argument to fork */
|
if (mode == 0) { /* argument to fork */
|
||||||
INTOFF;
|
INTOFF;
|
||||||
exitstatus = waitforjob(jp);
|
exitstatus = waitforjob(jp, &realstatus);
|
||||||
INTON;
|
INTON;
|
||||||
|
if (iflag && loopnest > 0 && WIFSIGNALED(realstatus)) {
|
||||||
|
evalskip = SKIPBREAK;
|
||||||
|
skipcount = loopnest;
|
||||||
|
}
|
||||||
} else if (mode == 2) {
|
} else if (mode == 2) {
|
||||||
backcmd->fd = pip[0];
|
backcmd->fd = pip[0];
|
||||||
close(pip[1]);
|
close(pip[1]);
|
||||||
|
@ -834,6 +894,8 @@ parent: /* parent process gets here (if we forked) */
|
||||||
out:
|
out:
|
||||||
if (lastarg)
|
if (lastarg)
|
||||||
setvar("_", lastarg, 0);
|
setvar("_", lastarg, 0);
|
||||||
|
if (do_clearcmdentry)
|
||||||
|
clearcmdentry(0);
|
||||||
popstackmark(&smark);
|
popstackmark(&smark);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -847,13 +909,14 @@ out:
|
||||||
*/
|
*/
|
||||||
|
|
||||||
STATIC void
|
STATIC void
|
||||||
prehash(n)
|
prehash(union node *n)
|
||||||
union node *n;
|
|
||||||
{
|
{
|
||||||
struct cmdentry entry;
|
struct cmdentry entry;
|
||||||
|
|
||||||
if (n->type == NCMD && goodname(n->ncmd.args->narg.text))
|
if (n->type == NCMD && n->ncmd.args)
|
||||||
find_command(n->ncmd.args->narg.text, &entry, 0);
|
if (goodname(n->ncmd.args->narg.text))
|
||||||
|
find_command(n->ncmd.args->narg.text, &entry, 0,
|
||||||
|
pathval());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -868,8 +931,14 @@ prehash(n)
|
||||||
* specified variables.
|
* specified variables.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
bltincmd(argc, argv) char **argv; {
|
int
|
||||||
|
bltincmd(int argc __unused, char **argv __unused)
|
||||||
|
{
|
||||||
listsetvar(cmdenviron);
|
listsetvar(cmdenviron);
|
||||||
|
/*
|
||||||
|
* Preserve exitstatus of a previous possible redirection
|
||||||
|
* as POSIX mandates
|
||||||
|
*/
|
||||||
return exitstatus;
|
return exitstatus;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -885,12 +954,11 @@ bltincmd(argc, argv) char **argv; {
|
||||||
* in the standard shell so we don't make it one here.
|
* in the standard shell so we don't make it one here.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
breakcmd(argc, argv) char **argv; {
|
int
|
||||||
int n;
|
breakcmd(int argc, char **argv)
|
||||||
|
{
|
||||||
|
int n = argc > 1 ? number(argv[1]) : 1;
|
||||||
|
|
||||||
n = 1;
|
|
||||||
if (argc > 1)
|
|
||||||
n = number(argv[1]);
|
|
||||||
if (n > loopnest)
|
if (n > loopnest)
|
||||||
n = loopnest;
|
n = loopnest;
|
||||||
if (n > 0) {
|
if (n > 0) {
|
||||||
|
@ -900,40 +968,108 @@ breakcmd(argc, argv) char **argv; {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The `command' command.
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
commandcmd(int argc, char **argv)
|
||||||
|
{
|
||||||
|
static char stdpath[] = _PATH_STDPATH;
|
||||||
|
struct jmploc loc, *old;
|
||||||
|
struct strlist *sp;
|
||||||
|
char *path;
|
||||||
|
int ch;
|
||||||
|
|
||||||
|
for (sp = cmdenviron; sp ; sp = sp->next)
|
||||||
|
setvareq(sp->text, VEXPORT|VSTACK);
|
||||||
|
path = pathval();
|
||||||
|
|
||||||
|
optind = optreset = 1;
|
||||||
|
opterr = 0;
|
||||||
|
while ((ch = getopt(argc, argv, "p")) != -1) {
|
||||||
|
switch (ch) {
|
||||||
|
case 'p':
|
||||||
|
path = stdpath;
|
||||||
|
break;
|
||||||
|
case '?':
|
||||||
|
default:
|
||||||
|
error("unknown option: -%c", optopt);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
argc -= optind;
|
||||||
|
argv += optind;
|
||||||
|
|
||||||
|
if (argc != 0) {
|
||||||
|
old = handler;
|
||||||
|
handler = &loc;
|
||||||
|
if (setjmp(handler->loc) == 0)
|
||||||
|
shellexec(argv, environment(), path, 0);
|
||||||
|
handler = old;
|
||||||
|
if (exception == EXEXEC)
|
||||||
|
exit(exerrno);
|
||||||
|
exraise(exception);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Do nothing successfully if no command was specified;
|
||||||
|
* ksh also does this.
|
||||||
|
*/
|
||||||
|
exit(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The return command.
|
* The return command.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
returncmd(argc, argv) char **argv; {
|
int
|
||||||
int ret;
|
returncmd(int argc, char **argv)
|
||||||
|
{
|
||||||
|
int ret = argc > 1 ? number(argv[1]) : oexitstatus;
|
||||||
|
|
||||||
ret = oexitstatus;
|
|
||||||
if (argc > 1)
|
|
||||||
ret = number(argv[1]);
|
|
||||||
if (funcnest) {
|
if (funcnest) {
|
||||||
evalskip = SKIPFUNC;
|
evalskip = SKIPFUNC;
|
||||||
skipcount = 1;
|
skipcount = 1;
|
||||||
|
} else {
|
||||||
|
/* skip the rest of the file */
|
||||||
|
evalskip = SKIPFILE;
|
||||||
|
skipcount = 1;
|
||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
truecmd(argc, argv) char **argv; {
|
int
|
||||||
return strcmp(argv[0], "false") == 0 ? 1 : 0;
|
falsecmd(int argc __unused, char **argv __unused)
|
||||||
|
{
|
||||||
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
execcmd(argc, argv) char **argv; {
|
int
|
||||||
|
truecmd(int argc __unused, char **argv __unused)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int
|
||||||
|
execcmd(int argc, char **argv)
|
||||||
|
{
|
||||||
if (argc > 1) {
|
if (argc > 1) {
|
||||||
|
struct strlist *sp;
|
||||||
|
|
||||||
iflag = 0; /* exit on error */
|
iflag = 0; /* exit on error */
|
||||||
setinteractive(0);
|
mflag = 0;
|
||||||
#if JOBS
|
optschanged();
|
||||||
jflag = 0;
|
for (sp = cmdenviron; sp ; sp = sp->next)
|
||||||
setjobctl(0);
|
setvareq(sp->text, VEXPORT|VSTACK);
|
||||||
#endif
|
|
||||||
shellexec(argv + 1, environment(), pathval(), 0);
|
shellexec(argv + 1, environment(), pathval(), 0);
|
||||||
|
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* $PchId: eval.c,v 1.7 2006/04/10 14:46:14 philip Exp $
|
||||||
|
*/
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/*-
|
/*-
|
||||||
* Copyright (c) 1991 The Regents of the University of California.
|
* Copyright (c) 1991, 1993
|
||||||
* All rights reserved.
|
* The Regents of the University of California. All rights reserved.
|
||||||
*
|
*
|
||||||
* This code is derived from software contributed to Berkeley by
|
* This code is derived from software contributed to Berkeley by
|
||||||
* Kenneth Almquist.
|
* Kenneth Almquist.
|
||||||
|
@ -13,10 +13,6 @@
|
||||||
* 2. Redistributions in binary form must reproduce the above copyright
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
* notice, this list of conditions and the following disclaimer in the
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
* documentation and/or other materials provided with the distribution.
|
* documentation and/or other materials provided with the distribution.
|
||||||
* 3. All advertising materials mentioning features or use of this software
|
|
||||||
* must display the following acknowledgement:
|
|
||||||
* This product includes software developed by the University of
|
|
||||||
* California, Berkeley and its contributors.
|
|
||||||
* 4. Neither the name of the University nor the names of its contributors
|
* 4. Neither the name of the University nor the names of its contributors
|
||||||
* may be used to endorse or promote products derived from this software
|
* may be used to endorse or promote products derived from this software
|
||||||
* without specific prior written permission.
|
* without specific prior written permission.
|
||||||
|
@ -33,7 +29,8 @@
|
||||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||||
* SUCH DAMAGE.
|
* SUCH DAMAGE.
|
||||||
*
|
*
|
||||||
* @(#)eval.h 5.2 (Berkeley) 4/12/91
|
* @(#)eval.h 8.2 (Berkeley) 5/4/95
|
||||||
|
* $FreeBSD: src/bin/sh/eval.h,v 1.10 2004/04/06 20:06:51 markm Exp $
|
||||||
*/
|
*/
|
||||||
|
|
||||||
extern char *commandname; /* currently executing command */
|
extern char *commandname; /* currently executing command */
|
||||||
|
@ -48,18 +45,30 @@ struct backcmd { /* result of evalbackcmd */
|
||||||
struct job *jp; /* job structure for command */
|
struct job *jp; /* job structure for command */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
int evalcmd(int, char **);
|
||||||
#ifdef __STDC__
|
|
||||||
void evalstring(char *);
|
void evalstring(char *);
|
||||||
union node; /* BLETCH for ansi C */
|
union node; /* BLETCH for ansi C */
|
||||||
void evaltree(union node *, int);
|
void evaltree(union node *, int);
|
||||||
void evalbackcmd(union node *, struct backcmd *);
|
void evalbackcmd(union node *, struct backcmd *);
|
||||||
#else
|
int bltincmd(int, char **);
|
||||||
void evalstring();
|
int breakcmd(int, char **);
|
||||||
void evaltree();
|
int returncmd(int, char **);
|
||||||
void evalbackcmd();
|
int falsecmd(int, char **);
|
||||||
#endif
|
int truecmd(int, char **);
|
||||||
|
int execcmd(int, char **);
|
||||||
|
int commandcmd(int, char **);
|
||||||
|
|
||||||
/* in_function returns nonzero if we are currently evaluating a function */
|
/* in_function returns nonzero if we are currently evaluating a function */
|
||||||
#define in_function() funcnest
|
#define in_function() funcnest
|
||||||
extern int funcnest;
|
extern int funcnest;
|
||||||
|
extern int evalskip;
|
||||||
|
|
||||||
|
/* reasons for skipping commands (see comment on breakcmd routine) */
|
||||||
|
#define SKIPBREAK 1
|
||||||
|
#define SKIPCONT 2
|
||||||
|
#define SKIPFUNC 3
|
||||||
|
#define SKIPFILE 4
|
||||||
|
|
||||||
|
/*
|
||||||
|
* $PchId: eval.h,v 1.3 2006/03/30 15:39:25 philip Exp $
|
||||||
|
*/
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/*-
|
/*-
|
||||||
* Copyright (c) 1991 The Regents of the University of California.
|
* Copyright (c) 1991, 1993
|
||||||
* All rights reserved.
|
* The Regents of the University of California. All rights reserved.
|
||||||
*
|
*
|
||||||
* This code is derived from software contributed to Berkeley by
|
* This code is derived from software contributed to Berkeley by
|
||||||
* Kenneth Almquist.
|
* Kenneth Almquist.
|
||||||
|
@ -13,10 +13,6 @@
|
||||||
* 2. Redistributions in binary form must reproduce the above copyright
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
* notice, this list of conditions and the following disclaimer in the
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
* documentation and/or other materials provided with the distribution.
|
* documentation and/or other materials provided with the distribution.
|
||||||
* 3. All advertising materials mentioning features or use of this software
|
|
||||||
* must display the following acknowledgement:
|
|
||||||
* This product includes software developed by the University of
|
|
||||||
* California, Berkeley and its contributors.
|
|
||||||
* 4. Neither the name of the University nor the names of its contributors
|
* 4. Neither the name of the University nor the names of its contributors
|
||||||
* may be used to endorse or promote products derived from this software
|
* may be used to endorse or promote products derived from this software
|
||||||
* without specific prior written permission.
|
* without specific prior written permission.
|
||||||
|
@ -35,8 +31,21 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef lint
|
#ifndef lint
|
||||||
static char sccsid[] = "@(#)exec.c 5.2 (Berkeley) 3/13/91";
|
#if 0
|
||||||
|
static char sccsid[] = "@(#)exec.c 8.4 (Berkeley) 6/8/95";
|
||||||
|
#endif
|
||||||
#endif /* not lint */
|
#endif /* not lint */
|
||||||
|
/*
|
||||||
|
#include <sys/cdefs.h>
|
||||||
|
__FBSDID("$FreeBSD: src/bin/sh/exec.c,v 1.24.2.1 2004/09/30 04:41:55 des Exp $");
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* When commands are first encountered, they are entered in a hash table.
|
* When commands are first encountered, they are entered in a hash table.
|
||||||
|
@ -64,11 +73,9 @@ static char sccsid[] = "@(#)exec.c 5.2 (Berkeley) 3/13/91";
|
||||||
#include "error.h"
|
#include "error.h"
|
||||||
#include "init.h"
|
#include "init.h"
|
||||||
#include "mystring.h"
|
#include "mystring.h"
|
||||||
#include <sys/types.h>
|
#include "show.h"
|
||||||
#include <sys/stat.h>
|
#include "jobs.h"
|
||||||
#include <fcntl.h>
|
#include "alias.h"
|
||||||
#include <errno.h>
|
|
||||||
#include <limits.h>
|
|
||||||
|
|
||||||
|
|
||||||
#define CMDTABLESIZE 31 /* should be prime */
|
#define CMDTABLESIZE 31 /* should be prime */
|
||||||
|
@ -87,23 +94,14 @@ struct tblentry {
|
||||||
|
|
||||||
STATIC struct tblentry *cmdtable[CMDTABLESIZE];
|
STATIC struct tblentry *cmdtable[CMDTABLESIZE];
|
||||||
STATIC int builtinloc = -1; /* index in path of %builtin, or -1 */
|
STATIC int builtinloc = -1; /* index in path of %builtin, or -1 */
|
||||||
|
int exerrno = 0; /* Last exec error */
|
||||||
|
|
||||||
|
|
||||||
#ifdef __STDC__
|
|
||||||
STATIC void tryexec(char *, char **, char **);
|
STATIC void tryexec(char *, char **, char **);
|
||||||
STATIC void execinterp(char **, char **);
|
STATIC void printentry(struct tblentry *, int);
|
||||||
STATIC void printentry(struct tblentry *);
|
|
||||||
STATIC void clearcmdentry(int);
|
|
||||||
STATIC struct tblentry *cmdlookup(char *, int);
|
STATIC struct tblentry *cmdlookup(char *, int);
|
||||||
STATIC void delete_cmd_entry(void);
|
STATIC void delete_cmd_entry(void);
|
||||||
#else
|
STATIC void addcmdentry(char *, struct cmdentry *);
|
||||||
STATIC void tryexec();
|
|
||||||
STATIC void execinterp();
|
|
||||||
STATIC void printentry();
|
|
||||||
STATIC void clearcmdentry();
|
|
||||||
STATIC struct tblentry *cmdlookup();
|
|
||||||
STATIC void delete_cmd_entry();
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -113,9 +111,7 @@ STATIC void delete_cmd_entry();
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void
|
void
|
||||||
shellexec(argv, envp, path, index)
|
shellexec(char **argv, char **envp, char *path, int index)
|
||||||
char **argv, **envp;
|
|
||||||
char *path;
|
|
||||||
{
|
{
|
||||||
char *cmdname;
|
char *cmdname;
|
||||||
int e;
|
int e;
|
||||||
|
@ -134,40 +130,37 @@ shellexec(argv, envp, path, index)
|
||||||
stunalloc(cmdname);
|
stunalloc(cmdname);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
error2(argv[0], errmsg(e, E_EXEC));
|
|
||||||
|
/* Map to POSIX errors */
|
||||||
|
switch (e) {
|
||||||
|
case EACCES:
|
||||||
|
exerrno = 126;
|
||||||
|
break;
|
||||||
|
case ENOENT:
|
||||||
|
exerrno = 127;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
exerrno = 2;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (e == ENOENT || e == ENOTDIR)
|
||||||
|
exerror(EXEXEC, "%s: not found", argv[0]);
|
||||||
|
exerror(EXEXEC, "%s: %s", argv[0], strerror(e));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
STATIC void
|
STATIC void
|
||||||
tryexec(cmd, argv, envp)
|
tryexec(char *cmd, char **argv, char **envp)
|
||||||
char *cmd;
|
|
||||||
char **argv;
|
|
||||||
char **envp;
|
|
||||||
{
|
{
|
||||||
int e;
|
int e;
|
||||||
char *p;
|
|
||||||
|
|
||||||
#ifdef SYSV
|
|
||||||
do {
|
|
||||||
execve(cmd, argv, envp);
|
execve(cmd, argv, envp);
|
||||||
} while (errno == EINTR);
|
#if !__minix_vmd
|
||||||
#else
|
|
||||||
execve(cmd, argv, envp);
|
|
||||||
#endif
|
|
||||||
#if HASHBANG
|
|
||||||
e = errno;
|
e = errno;
|
||||||
if (e == ENOEXEC) {
|
if (e == ENOEXEC) {
|
||||||
initshellproc();
|
initshellproc();
|
||||||
setinputfile(cmd, 0);
|
setinputfile(cmd, 0);
|
||||||
commandname = arg0 = savestr(argv[0]);
|
commandname = arg0 = savestr(argv[0]);
|
||||||
#ifndef BSD
|
|
||||||
pgetc(); pungetc(); /* fill up input buffer */
|
|
||||||
p = parsenextc;
|
|
||||||
if (parsenleft > 2 && p[0] == '#' && p[1] == '!') {
|
|
||||||
argv[0] = cmd;
|
|
||||||
execinterp(argv, envp);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
setparam(argv + 1);
|
setparam(argv + 1);
|
||||||
exraise(EXSHELLPROC);
|
exraise(EXSHELLPROC);
|
||||||
/*NOTREACHED*/
|
/*NOTREACHED*/
|
||||||
|
@ -176,88 +169,6 @@ tryexec(cmd, argv, envp)
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#if !defined(BSD) && HASHBANG
|
|
||||||
/*
|
|
||||||
* Execute an interpreter introduced by "#!", for systems where this
|
|
||||||
* feature has not been built into the kernel. If the interpreter is
|
|
||||||
* the shell, return (effectively ignoring the "#!"). If the execution
|
|
||||||
* of the interpreter fails, exit.
|
|
||||||
*
|
|
||||||
* This code peeks inside the input buffer in order to avoid actually
|
|
||||||
* reading any input. It would benefit from a rewrite.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#define NEWARGS 5
|
|
||||||
|
|
||||||
STATIC void
|
|
||||||
execinterp(argv, envp)
|
|
||||||
char **argv, **envp;
|
|
||||||
{
|
|
||||||
int n;
|
|
||||||
char *inp;
|
|
||||||
char *outp;
|
|
||||||
char c;
|
|
||||||
char *p;
|
|
||||||
char **ap;
|
|
||||||
char *newargs[NEWARGS];
|
|
||||||
int i;
|
|
||||||
char **ap2;
|
|
||||||
char **new;
|
|
||||||
|
|
||||||
n = parsenleft - 2;
|
|
||||||
inp = parsenextc + 2;
|
|
||||||
ap = newargs;
|
|
||||||
for (;;) {
|
|
||||||
while (--n >= 0 && (*inp == ' ' || *inp == '\t'))
|
|
||||||
inp++;
|
|
||||||
if (n < 0)
|
|
||||||
goto bad;
|
|
||||||
if ((c = *inp++) == '\n')
|
|
||||||
break;
|
|
||||||
if (ap == &newargs[NEWARGS])
|
|
||||||
bad: error("Bad #! line");
|
|
||||||
STARTSTACKSTR(outp);
|
|
||||||
do {
|
|
||||||
STPUTC(c, outp);
|
|
||||||
} while (--n >= 0 && (c = *inp++) != ' ' && c != '\t' && c != '\n');
|
|
||||||
STPUTC('\0', outp);
|
|
||||||
n++, inp--;
|
|
||||||
*ap++ = grabstackstr(outp);
|
|
||||||
}
|
|
||||||
#if !__minix
|
|
||||||
if (ap == newargs + 1) { /* if no args, maybe no exec is needed */
|
|
||||||
p = newargs[0];
|
|
||||||
for (;;) {
|
|
||||||
if (equal(p, "sh") || equal(p, "ash")) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
while (*p != '/') {
|
|
||||||
if (*p == '\0')
|
|
||||||
goto break2;
|
|
||||||
p++;
|
|
||||||
}
|
|
||||||
p++;
|
|
||||||
}
|
|
||||||
break2:;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
i = (char *)ap - (char *)newargs; /* size in bytes */
|
|
||||||
if (i == 0)
|
|
||||||
error("Bad #! line");
|
|
||||||
for (ap2 = argv ; *ap2++ != NULL ; );
|
|
||||||
new = ckmalloc(i + ((char *)ap2 - (char *)argv));
|
|
||||||
ap = newargs, ap2 = new;
|
|
||||||
while ((i -= sizeof (char **)) >= 0)
|
|
||||||
*ap2++ = *ap++;
|
|
||||||
ap = argv;
|
|
||||||
while (*ap2++ = *ap++);
|
|
||||||
shellexec(new, envp, pathval(), 0);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Do a path search. The variable path (passed by reference) should be
|
* Do a path search. The variable path (passed by reference) should be
|
||||||
* set to the start of the path before the first call; padvance will update
|
* set to the start of the path before the first call; padvance will update
|
||||||
|
@ -271,11 +182,9 @@ break2:;
|
||||||
char *pathopt;
|
char *pathopt;
|
||||||
|
|
||||||
char *
|
char *
|
||||||
padvance(path, name)
|
padvance(char **path, char *name)
|
||||||
char **path;
|
|
||||||
char *name;
|
|
||||||
{
|
{
|
||||||
register char *p, *q;
|
char *p, *q;
|
||||||
char *start;
|
char *start;
|
||||||
int len;
|
int len;
|
||||||
|
|
||||||
|
@ -288,7 +197,7 @@ padvance(path, name)
|
||||||
growstackblock();
|
growstackblock();
|
||||||
q = stackblock();
|
q = stackblock();
|
||||||
if (p != start) {
|
if (p != start) {
|
||||||
bcopy(start, q, p - start);
|
memcpy(q, start, p - start);
|
||||||
q += p - start;
|
q += p - start;
|
||||||
*q++ = '/';
|
*q++ = '/';
|
||||||
}
|
}
|
||||||
|
@ -310,7 +219,9 @@ padvance(path, name)
|
||||||
/*** Command hashing code ***/
|
/*** Command hashing code ***/
|
||||||
|
|
||||||
|
|
||||||
hashcmd(argc, argv) char **argv; {
|
int
|
||||||
|
hashcmd(int argc __unused, char **argv __unused)
|
||||||
|
{
|
||||||
struct tblentry **pp;
|
struct tblentry **pp;
|
||||||
struct tblentry *cmdp;
|
struct tblentry *cmdp;
|
||||||
int c;
|
int c;
|
||||||
|
@ -318,14 +229,6 @@ hashcmd(argc, argv) char **argv; {
|
||||||
struct cmdentry entry;
|
struct cmdentry entry;
|
||||||
char *name;
|
char *name;
|
||||||
|
|
||||||
if (argc <= 1) {
|
|
||||||
for (pp = cmdtable ; pp < &cmdtable[CMDTABLESIZE] ; pp++) {
|
|
||||||
for (cmdp = *pp ; cmdp ; cmdp = cmdp->next) {
|
|
||||||
printentry(cmdp);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
verbose = 0;
|
verbose = 0;
|
||||||
while ((c = nextopt("rv")) != '\0') {
|
while ((c = nextopt("rv")) != '\0') {
|
||||||
if (c == 'r') {
|
if (c == 'r') {
|
||||||
|
@ -334,16 +237,28 @@ hashcmd(argc, argv) char **argv; {
|
||||||
verbose++;
|
verbose++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (*argptr == NULL) {
|
||||||
|
for (pp = cmdtable ; pp < &cmdtable[CMDTABLESIZE] ; pp++) {
|
||||||
|
for (cmdp = *pp ; cmdp ; cmdp = cmdp->next) {
|
||||||
|
if (cmdp->cmdtype == CMDNORMAL)
|
||||||
|
printentry(cmdp, verbose);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
while ((name = *argptr) != NULL) {
|
while ((name = *argptr) != NULL) {
|
||||||
if ((cmdp = cmdlookup(name, 0)) != NULL
|
if ((cmdp = cmdlookup(name, 0)) != NULL
|
||||||
&& (cmdp->cmdtype == CMDNORMAL
|
&& (cmdp->cmdtype == CMDNORMAL
|
||||||
|| cmdp->cmdtype == CMDBUILTIN && builtinloc >= 0))
|
|| (cmdp->cmdtype == CMDBUILTIN && builtinloc >= 0)))
|
||||||
delete_cmd_entry();
|
delete_cmd_entry();
|
||||||
find_command(name, &entry, 1);
|
find_command(name, &entry, 1, pathval());
|
||||||
if (verbose) {
|
if (verbose) {
|
||||||
if (entry.cmdtype != CMDUNKNOWN) { /* if no error msg */
|
if (entry.cmdtype != CMDUNKNOWN) { /* if no error msg */
|
||||||
cmdp = cmdlookup(name, 0);
|
cmdp = cmdlookup(name, 0);
|
||||||
printentry(cmdp);
|
if (cmdp != NULL)
|
||||||
|
printentry(cmdp, verbose);
|
||||||
|
else
|
||||||
|
outfmt(&errout, "%s: not found\n", name);
|
||||||
}
|
}
|
||||||
flushall();
|
flushall();
|
||||||
}
|
}
|
||||||
|
@ -354,8 +269,7 @@ hashcmd(argc, argv) char **argv; {
|
||||||
|
|
||||||
|
|
||||||
STATIC void
|
STATIC void
|
||||||
printentry(cmdp)
|
printentry(struct tblentry *cmdp, int verbose)
|
||||||
struct tblentry *cmdp;
|
|
||||||
{
|
{
|
||||||
int index;
|
int index;
|
||||||
char *path;
|
char *path;
|
||||||
|
@ -373,6 +287,14 @@ printentry(cmdp)
|
||||||
out1fmt("builtin %s", cmdp->cmdname);
|
out1fmt("builtin %s", cmdp->cmdname);
|
||||||
} else if (cmdp->cmdtype == CMDFUNCTION) {
|
} else if (cmdp->cmdtype == CMDFUNCTION) {
|
||||||
out1fmt("function %s", cmdp->cmdname);
|
out1fmt("function %s", cmdp->cmdname);
|
||||||
|
if (verbose) {
|
||||||
|
INTOFF;
|
||||||
|
name = commandtext(cmdp->param.func);
|
||||||
|
out1c(' ');
|
||||||
|
out1str(name);
|
||||||
|
ckfree(name);
|
||||||
|
INTON;
|
||||||
|
}
|
||||||
#if DEBUG
|
#if DEBUG
|
||||||
} else {
|
} else {
|
||||||
error("internal error: cmdtype %d", cmdp->cmdtype);
|
error("internal error: cmdtype %d", cmdp->cmdtype);
|
||||||
|
@ -391,14 +313,11 @@ printentry(cmdp)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void
|
void
|
||||||
find_command(name, entry, printerr)
|
find_command(char *name, struct cmdentry *entry, int printerr, char *path)
|
||||||
char *name;
|
|
||||||
struct cmdentry *entry;
|
|
||||||
{
|
{
|
||||||
struct tblentry *cmdp;
|
struct tblentry *cmdp;
|
||||||
int index;
|
int index;
|
||||||
int prev;
|
int prev;
|
||||||
char *path;
|
|
||||||
char *fullname;
|
char *fullname;
|
||||||
struct stat statb;
|
struct stat statb;
|
||||||
int e;
|
int e;
|
||||||
|
@ -434,7 +353,6 @@ find_command(name, entry, printerr)
|
||||||
prev = cmdp->param.index;
|
prev = cmdp->param.index;
|
||||||
}
|
}
|
||||||
|
|
||||||
path = pathval();
|
|
||||||
e = ENOENT;
|
e = ENOENT;
|
||||||
index = -1;
|
index = -1;
|
||||||
loop:
|
loop:
|
||||||
|
@ -464,17 +382,13 @@ loop:
|
||||||
TRACE(("searchexec \"%s\": no change\n", name));
|
TRACE(("searchexec \"%s\": no change\n", name));
|
||||||
goto success;
|
goto success;
|
||||||
}
|
}
|
||||||
while (stat(fullname, &statb) < 0) {
|
if (stat(fullname, &statb) < 0) {
|
||||||
#ifdef SYSV
|
|
||||||
if (errno == EINTR)
|
|
||||||
continue;
|
|
||||||
#endif
|
|
||||||
if (errno != ENOENT && errno != ENOTDIR)
|
if (errno != ENOENT && errno != ENOTDIR)
|
||||||
e = errno;
|
e = errno;
|
||||||
goto loop;
|
goto loop;
|
||||||
}
|
}
|
||||||
e = EACCES; /* if we fail, this will be the error */
|
e = EACCES; /* if we fail, this will be the error */
|
||||||
if ((statb.st_mode & S_IFMT) != S_IFREG)
|
if (!S_ISREG(statb.st_mode))
|
||||||
goto loop;
|
goto loop;
|
||||||
if (pathopt) { /* this is a %func directory */
|
if (pathopt) { /* this is a %func directory */
|
||||||
stalloc(strlen(fullname) + 1);
|
stalloc(strlen(fullname) + 1);
|
||||||
|
@ -484,6 +398,7 @@ loop:
|
||||||
stunalloc(fullname);
|
stunalloc(fullname);
|
||||||
goto success;
|
goto success;
|
||||||
}
|
}
|
||||||
|
#ifdef notdef
|
||||||
if (statb.st_uid == geteuid()) {
|
if (statb.st_uid == geteuid()) {
|
||||||
if ((statb.st_mode & 0100) == 0)
|
if ((statb.st_mode & 0100) == 0)
|
||||||
goto loop;
|
goto loop;
|
||||||
|
@ -491,23 +406,10 @@ loop:
|
||||||
if ((statb.st_mode & 010) == 0)
|
if ((statb.st_mode & 010) == 0)
|
||||||
goto loop;
|
goto loop;
|
||||||
} else {
|
} else {
|
||||||
#if __minix_vmd || defined(BSD)
|
|
||||||
gid_t group_list[NGROUPS_MAX];
|
|
||||||
int ngroups, i;
|
|
||||||
|
|
||||||
ngroups = getgroups(NGROUPS_MAX, group_list);
|
|
||||||
|
|
||||||
for (i = 0; i < ngroups; i++) {
|
|
||||||
if (statb.st_gid == group_list[i]) break;
|
|
||||||
}
|
|
||||||
if (i < ngroups) {
|
|
||||||
if ((statb.st_mode & 010) == 0)
|
|
||||||
goto loop;
|
|
||||||
} else
|
|
||||||
#endif
|
|
||||||
if ((statb.st_mode & 01) == 0)
|
if ((statb.st_mode & 01) == 0)
|
||||||
goto loop;
|
goto loop;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
TRACE(("searchexec \"%s\" returns \"%s\"\n", name, fullname));
|
TRACE(("searchexec \"%s\" returns \"%s\"\n", name, fullname));
|
||||||
INTOFF;
|
INTOFF;
|
||||||
cmdp = cmdlookup(name, 1);
|
cmdp = cmdlookup(name, 1);
|
||||||
|
@ -520,8 +422,12 @@ loop:
|
||||||
/* We failed. If there was an entry for this command, delete it */
|
/* We failed. If there was an entry for this command, delete it */
|
||||||
if (cmdp)
|
if (cmdp)
|
||||||
delete_cmd_entry();
|
delete_cmd_entry();
|
||||||
if (printerr)
|
if (printerr) {
|
||||||
outfmt(out2, "%s: %s\n", name, errmsg(e, E_EXEC));
|
if (e == ENOENT || e == ENOTDIR)
|
||||||
|
outfmt(out2, "%s: not found\n", name);
|
||||||
|
else
|
||||||
|
outfmt(out2, "%s: %s\n", name, strerror(e));
|
||||||
|
}
|
||||||
entry->cmdtype = CMDUNKNOWN;
|
entry->cmdtype = CMDUNKNOWN;
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
@ -538,10 +444,9 @@ success:
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int
|
int
|
||||||
find_builtin(name)
|
find_builtin(char *name)
|
||||||
char *name;
|
|
||||||
{
|
{
|
||||||
const register struct builtincmd *bp;
|
const struct builtincmd *bp;
|
||||||
|
|
||||||
for (bp = builtincmd ; bp->name ; bp++) {
|
for (bp = builtincmd ; bp->name ; bp++) {
|
||||||
if (*bp->name == *name && equal(bp->name, name))
|
if (*bp->name == *name && equal(bp->name, name))
|
||||||
|
@ -558,14 +463,15 @@ find_builtin(name)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void
|
void
|
||||||
hashcd() {
|
hashcd(void)
|
||||||
|
{
|
||||||
struct tblentry **pp;
|
struct tblentry **pp;
|
||||||
struct tblentry *cmdp;
|
struct tblentry *cmdp;
|
||||||
|
|
||||||
for (pp = cmdtable ; pp < &cmdtable[CMDTABLESIZE] ; pp++) {
|
for (pp = cmdtable ; pp < &cmdtable[CMDTABLESIZE] ; pp++) {
|
||||||
for (cmdp = *pp ; cmdp ; cmdp = cmdp->next) {
|
for (cmdp = *pp ; cmdp ; cmdp = cmdp->next) {
|
||||||
if (cmdp->cmdtype == CMDNORMAL
|
if (cmdp->cmdtype == CMDNORMAL
|
||||||
|| cmdp->cmdtype == CMDBUILTIN && builtinloc >= 0)
|
|| (cmdp->cmdtype == CMDBUILTIN && builtinloc >= 0))
|
||||||
cmdp->rehash = 1;
|
cmdp->rehash = 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -580,10 +486,9 @@ hashcd() {
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void
|
void
|
||||||
changepath(newval)
|
changepath(const char *newval)
|
||||||
char *newval;
|
|
||||||
{
|
{
|
||||||
char *old, *new;
|
const char *old, *new;
|
||||||
int index;
|
int index;
|
||||||
int firstchange;
|
int firstchange;
|
||||||
int bltin;
|
int bltin;
|
||||||
|
@ -596,8 +501,8 @@ changepath(newval)
|
||||||
for (;;) {
|
for (;;) {
|
||||||
if (*old != *new) {
|
if (*old != *new) {
|
||||||
firstchange = index;
|
firstchange = index;
|
||||||
if (*old == '\0' && *new == ':'
|
if ((*old == '\0' && *new == ':')
|
||||||
|| *old == ':' && *new == '\0')
|
|| (*old == ':' && *new == '\0'))
|
||||||
firstchange++;
|
firstchange++;
|
||||||
old = new; /* ignore subsequent differences */
|
old = new; /* ignore subsequent differences */
|
||||||
}
|
}
|
||||||
|
@ -624,8 +529,9 @@ changepath(newval)
|
||||||
* PATH which has changed.
|
* PATH which has changed.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
STATIC void
|
void
|
||||||
clearcmdentry(firstchange) {
|
clearcmdentry(int firstchange)
|
||||||
|
{
|
||||||
struct tblentry **tblp;
|
struct tblentry **tblp;
|
||||||
struct tblentry **pp;
|
struct tblentry **pp;
|
||||||
struct tblentry *cmdp;
|
struct tblentry *cmdp;
|
||||||
|
@ -634,8 +540,10 @@ clearcmdentry(firstchange) {
|
||||||
for (tblp = cmdtable ; tblp < &cmdtable[CMDTABLESIZE] ; tblp++) {
|
for (tblp = cmdtable ; tblp < &cmdtable[CMDTABLESIZE] ; tblp++) {
|
||||||
pp = tblp;
|
pp = tblp;
|
||||||
while ((cmdp = *pp) != NULL) {
|
while ((cmdp = *pp) != NULL) {
|
||||||
if (cmdp->cmdtype == CMDNORMAL && cmdp->param.index >= firstchange
|
if ((cmdp->cmdtype == CMDNORMAL &&
|
||||||
|| cmdp->cmdtype == CMDBUILTIN && builtinloc >= firstchange) {
|
cmdp->param.index >= firstchange)
|
||||||
|
|| (cmdp->cmdtype == CMDBUILTIN &&
|
||||||
|
builtinloc >= firstchange)) {
|
||||||
*pp = cmdp->next;
|
*pp = cmdp->next;
|
||||||
ckfree(cmdp);
|
ckfree(cmdp);
|
||||||
} else {
|
} else {
|
||||||
|
@ -652,15 +560,15 @@ clearcmdentry(firstchange) {
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifdef mkinit
|
#ifdef mkinit
|
||||||
MKINIT void deletefuncs();
|
INCLUDE "exec.h"
|
||||||
|
|
||||||
SHELLPROC {
|
SHELLPROC {
|
||||||
deletefuncs();
|
deletefuncs();
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
void
|
void
|
||||||
deletefuncs() {
|
deletefuncs(void)
|
||||||
|
{
|
||||||
struct tblentry **tblp;
|
struct tblentry **tblp;
|
||||||
struct tblentry **pp;
|
struct tblentry **pp;
|
||||||
struct tblentry *cmdp;
|
struct tblentry *cmdp;
|
||||||
|
@ -691,15 +599,14 @@ deletefuncs() {
|
||||||
* entry.
|
* entry.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
struct tblentry **lastcmdentry;
|
STATIC struct tblentry **lastcmdentry;
|
||||||
|
|
||||||
|
|
||||||
STATIC struct tblentry *
|
STATIC struct tblentry *
|
||||||
cmdlookup(name, add)
|
cmdlookup(char *name, int add)
|
||||||
char *name;
|
|
||||||
{
|
{
|
||||||
int hashval;
|
int hashval;
|
||||||
register char *p;
|
char *p;
|
||||||
struct tblentry *cmdp;
|
struct tblentry *cmdp;
|
||||||
struct tblentry **pp;
|
struct tblentry **pp;
|
||||||
|
|
||||||
|
@ -728,13 +635,13 @@ cmdlookup(name, add)
|
||||||
return cmdp;
|
return cmdp;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Delete the command entry returned on the last lookup.
|
* Delete the command entry returned on the last lookup.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
STATIC void
|
STATIC void
|
||||||
delete_cmd_entry() {
|
delete_cmd_entry(void)
|
||||||
|
{
|
||||||
struct tblentry *cmdp;
|
struct tblentry *cmdp;
|
||||||
|
|
||||||
INTOFF;
|
INTOFF;
|
||||||
|
@ -746,34 +653,13 @@ delete_cmd_entry() {
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef notdef
|
|
||||||
void
|
|
||||||
getcmdentry(name, entry)
|
|
||||||
char *name;
|
|
||||||
struct cmdentry *entry;
|
|
||||||
{
|
|
||||||
struct tblentry *cmdp = cmdlookup(name, 0);
|
|
||||||
|
|
||||||
if (cmdp) {
|
|
||||||
entry->u = cmdp->param;
|
|
||||||
entry->cmdtype = cmdp->cmdtype;
|
|
||||||
} else {
|
|
||||||
entry->cmdtype = CMDUNKNOWN;
|
|
||||||
entry->u.index = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Add a new command entry, replacing any existing command entry for
|
* Add a new command entry, replacing any existing command entry for
|
||||||
* the same name.
|
* the same name.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void
|
static void
|
||||||
addcmdentry(name, entry)
|
addcmdentry(char *name, struct cmdentry *entry)
|
||||||
char *name;
|
|
||||||
struct cmdentry *entry;
|
|
||||||
{
|
{
|
||||||
struct tblentry *cmdp;
|
struct tblentry *cmdp;
|
||||||
|
|
||||||
|
@ -793,9 +679,7 @@ addcmdentry(name, entry)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void
|
void
|
||||||
defun(name, func)
|
defun(char *name, union node *func)
|
||||||
char *name;
|
|
||||||
union node *func;
|
|
||||||
{
|
{
|
||||||
struct cmdentry entry;
|
struct cmdentry entry;
|
||||||
|
|
||||||
|
@ -811,14 +695,98 @@ defun(name, func)
|
||||||
* Delete a function if it exists.
|
* Delete a function if it exists.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void
|
int
|
||||||
unsetfunc(name)
|
unsetfunc(char *name)
|
||||||
char *name;
|
|
||||||
{
|
{
|
||||||
struct tblentry *cmdp;
|
struct tblentry *cmdp;
|
||||||
|
|
||||||
if ((cmdp = cmdlookup(name, 0)) != NULL && cmdp->cmdtype == CMDFUNCTION) {
|
if ((cmdp = cmdlookup(name, 0)) != NULL && cmdp->cmdtype == CMDFUNCTION) {
|
||||||
freefunc(cmdp->param.func);
|
freefunc(cmdp->param.func);
|
||||||
delete_cmd_entry();
|
delete_cmd_entry();
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Locate and print what a word is...
|
||||||
|
*/
|
||||||
|
|
||||||
|
int
|
||||||
|
typecmd(int argc, char **argv)
|
||||||
|
{
|
||||||
|
struct cmdentry entry;
|
||||||
|
struct tblentry *cmdp;
|
||||||
|
char **pp;
|
||||||
|
struct alias *ap;
|
||||||
|
int i;
|
||||||
|
int error = 0;
|
||||||
|
extern char *const parsekwd[];
|
||||||
|
|
||||||
|
for (i = 1; i < argc; i++) {
|
||||||
|
out1str(argv[i]);
|
||||||
|
/* First look at the keywords */
|
||||||
|
for (pp = (char **)parsekwd; *pp; pp++)
|
||||||
|
if (**pp == *argv[i] && equal(*pp, argv[i]))
|
||||||
|
break;
|
||||||
|
|
||||||
|
if (*pp) {
|
||||||
|
out1str(" is a shell keyword\n");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Then look at the aliases */
|
||||||
|
if ((ap = lookupalias(argv[i], 1)) != NULL) {
|
||||||
|
out1fmt(" is an alias for %s\n", ap->val);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Then check if it is a tracked alias */
|
||||||
|
if ((cmdp = cmdlookup(argv[i], 0)) != NULL) {
|
||||||
|
entry.cmdtype = cmdp->cmdtype;
|
||||||
|
entry.u = cmdp->param;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
/* Finally use brute force */
|
||||||
|
find_command(argv[i], &entry, 0, pathval());
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (entry.cmdtype) {
|
||||||
|
case CMDNORMAL: {
|
||||||
|
if (strchr(argv[i], '/') == NULL) {
|
||||||
|
char *path = pathval(), *name;
|
||||||
|
int j = entry.u.index;
|
||||||
|
do {
|
||||||
|
name = padvance(&path, argv[i]);
|
||||||
|
stunalloc(name);
|
||||||
|
} while (--j >= 0);
|
||||||
|
out1fmt(" is%s %s\n",
|
||||||
|
cmdp ? " a tracked alias for" : "", name);
|
||||||
|
} else {
|
||||||
|
if (access(argv[i], X_OK) == 0)
|
||||||
|
out1fmt(" is %s\n", argv[i]);
|
||||||
|
else
|
||||||
|
out1fmt(": %s\n", strerror(errno));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case CMDFUNCTION:
|
||||||
|
out1str(" is a shell function\n");
|
||||||
|
break;
|
||||||
|
|
||||||
|
case CMDBUILTIN:
|
||||||
|
out1str(" is a shell builtin\n");
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
out1str(": not found\n");
|
||||||
|
error |= 127;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* $PchId: exec.c,v 1.6 2006/04/10 14:47:03 philip Exp $
|
||||||
|
*/
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/*-
|
/*-
|
||||||
* Copyright (c) 1991 The Regents of the University of California.
|
* Copyright (c) 1991, 1993
|
||||||
* All rights reserved.
|
* The Regents of the University of California. All rights reserved.
|
||||||
*
|
*
|
||||||
* This code is derived from software contributed to Berkeley by
|
* This code is derived from software contributed to Berkeley by
|
||||||
* Kenneth Almquist.
|
* Kenneth Almquist.
|
||||||
|
@ -13,10 +13,6 @@
|
||||||
* 2. Redistributions in binary form must reproduce the above copyright
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
* notice, this list of conditions and the following disclaimer in the
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
* documentation and/or other materials provided with the distribution.
|
* documentation and/or other materials provided with the distribution.
|
||||||
* 3. All advertising materials mentioning features or use of this software
|
|
||||||
* must display the following acknowledgement:
|
|
||||||
* This product includes software developed by the University of
|
|
||||||
* California, Berkeley and its contributors.
|
|
||||||
* 4. Neither the name of the University nor the names of its contributors
|
* 4. Neither the name of the University nor the names of its contributors
|
||||||
* may be used to endorse or promote products derived from this software
|
* may be used to endorse or promote products derived from this software
|
||||||
* without specific prior written permission.
|
* without specific prior written permission.
|
||||||
|
@ -33,7 +29,8 @@
|
||||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||||
* SUCH DAMAGE.
|
* SUCH DAMAGE.
|
||||||
*
|
*
|
||||||
* @(#)exec.h 5.1 (Berkeley) 3/7/91
|
* @(#)exec.h 8.3 (Berkeley) 6/8/95
|
||||||
|
* $FreeBSD: src/bin/sh/exec.h,v 1.12 2004/04/06 20:06:51 markm Exp $
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* values of cmdtype */
|
/* values of cmdtype */
|
||||||
|
@ -53,23 +50,21 @@ struct cmdentry {
|
||||||
|
|
||||||
|
|
||||||
extern char *pathopt; /* set by padvance */
|
extern char *pathopt; /* set by padvance */
|
||||||
|
extern int exerrno; /* last exec error */
|
||||||
|
|
||||||
#ifdef __STDC__
|
|
||||||
void shellexec(char **, char **, char *, int);
|
void shellexec(char **, char **, char *, int);
|
||||||
char *padvance(char **, char *);
|
char *padvance(char **, char *);
|
||||||
void find_command(char *, struct cmdentry *, int);
|
int hashcmd(int, char **);
|
||||||
|
void find_command(char *, struct cmdentry *, int, char *);
|
||||||
int find_builtin(char *);
|
int find_builtin(char *);
|
||||||
void hashcd(void);
|
void hashcd(void);
|
||||||
void changepath(char *);
|
void changepath(const char *);
|
||||||
|
void deletefuncs(void);
|
||||||
void defun(char *, union node *);
|
void defun(char *, union node *);
|
||||||
void unsetfunc(char *);
|
int unsetfunc(char *);
|
||||||
#else
|
int typecmd(int, char **);
|
||||||
void shellexec();
|
void clearcmdentry(int);
|
||||||
char *padvance();
|
|
||||||
void find_command();
|
/*
|
||||||
int find_builtin();
|
* $PchId: exec.h,v 1.5 2006/04/10 14:47:34 philip Exp $
|
||||||
void hashcd();
|
*/
|
||||||
void changepath();
|
|
||||||
void defun();
|
|
||||||
void unsetfunc();
|
|
||||||
#endif
|
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -1,6 +1,6 @@
|
||||||
/*-
|
/*-
|
||||||
* Copyright (c) 1991 The Regents of the University of California.
|
* Copyright (c) 1991, 1993
|
||||||
* All rights reserved.
|
* The Regents of the University of California. All rights reserved.
|
||||||
*
|
*
|
||||||
* This code is derived from software contributed to Berkeley by
|
* This code is derived from software contributed to Berkeley by
|
||||||
* Kenneth Almquist.
|
* Kenneth Almquist.
|
||||||
|
@ -13,10 +13,6 @@
|
||||||
* 2. Redistributions in binary form must reproduce the above copyright
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
* notice, this list of conditions and the following disclaimer in the
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
* documentation and/or other materials provided with the distribution.
|
* documentation and/or other materials provided with the distribution.
|
||||||
* 3. All advertising materials mentioning features or use of this software
|
|
||||||
* must display the following acknowledgement:
|
|
||||||
* This product includes software developed by the University of
|
|
||||||
* California, Berkeley and its contributors.
|
|
||||||
* 4. Neither the name of the University nor the names of its contributors
|
* 4. Neither the name of the University nor the names of its contributors
|
||||||
* may be used to endorse or promote products derived from this software
|
* may be used to endorse or promote products derived from this software
|
||||||
* without specific prior written permission.
|
* without specific prior written permission.
|
||||||
|
@ -33,7 +29,8 @@
|
||||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||||
* SUCH DAMAGE.
|
* SUCH DAMAGE.
|
||||||
*
|
*
|
||||||
* @(#)expand.h 5.1 (Berkeley) 3/7/91
|
* @(#)expand.h 8.2 (Berkeley) 5/4/95
|
||||||
|
* $FreeBSD: src/bin/sh/expand.h,v 1.12 2004/04/06 20:06:51 markm Exp $
|
||||||
*/
|
*/
|
||||||
|
|
||||||
struct strlist {
|
struct strlist {
|
||||||
|
@ -47,17 +44,24 @@ struct arglist {
|
||||||
struct strlist **lastp;
|
struct strlist **lastp;
|
||||||
};
|
};
|
||||||
|
|
||||||
#ifdef __STDC__
|
/*
|
||||||
|
* expandarg() flags
|
||||||
|
*/
|
||||||
|
#define EXP_FULL 0x1 /* perform word splitting & file globbing */
|
||||||
|
#define EXP_TILDE 0x2 /* do normal tilde expansion */
|
||||||
|
#define EXP_VARTILDE 0x4 /* expand tildes in an assignment */
|
||||||
|
#define EXP_REDIR 0x8 /* file glob for a redirection (1 match only) */
|
||||||
|
#define EXP_CASE 0x10 /* keeps quotes around for CASE pattern */
|
||||||
|
|
||||||
|
|
||||||
union node;
|
union node;
|
||||||
void expandarg(union node *, struct arglist *, int);
|
|
||||||
void expandhere(union node *, int);
|
void expandhere(union node *, int);
|
||||||
int patmatch(char *, char *);
|
void expandarg(union node *, struct arglist *, int);
|
||||||
|
int patmatch(char *, char *, int);
|
||||||
void rmescapes(char *);
|
void rmescapes(char *);
|
||||||
int casematch(union node *, char *);
|
int casematch(union node *, char *);
|
||||||
#else
|
int wordexpcmd(int, char **);
|
||||||
void expandarg();
|
|
||||||
void expandhere();
|
/*
|
||||||
int patmatch();
|
* $PchId: expand.h,v 1.4 2006/03/30 14:50:52 philip Exp $
|
||||||
void rmescapes();
|
*/
|
||||||
int casematch();
|
|
||||||
#endif
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
# Copyright (c) 1991 The Regents of the University of California.
|
# Copyright (c) 1991, 1993
|
||||||
# All rights reserved.
|
# The Regents of the University of California. All rights reserved.
|
||||||
#
|
#
|
||||||
# This code is derived from software contributed to Berkeley by
|
# This code is derived from software contributed to Berkeley by
|
||||||
# Kenneth Almquist.
|
# Kenneth Almquist.
|
||||||
|
@ -12,10 +12,6 @@
|
||||||
# 2. Redistributions in binary form must reproduce the above copyright
|
# 2. Redistributions in binary form must reproduce the above copyright
|
||||||
# notice, this list of conditions and the following disclaimer in the
|
# notice, this list of conditions and the following disclaimer in the
|
||||||
# documentation and/or other materials provided with the distribution.
|
# documentation and/or other materials provided with the distribution.
|
||||||
# 3. All advertising materials mentioning features or use of this software
|
|
||||||
# must display the following acknowledgement:
|
|
||||||
# This product includes software developed by the University of
|
|
||||||
# California, Berkeley and its contributors.
|
|
||||||
# 4. Neither the name of the University nor the names of its contributors
|
# 4. Neither the name of the University nor the names of its contributors
|
||||||
# may be used to endorse or promote products derived from this software
|
# may be used to endorse or promote products derived from this software
|
||||||
# without specific prior written permission.
|
# without specific prior written permission.
|
||||||
|
@ -32,7 +28,8 @@
|
||||||
# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||||
# SUCH DAMAGE.
|
# SUCH DAMAGE.
|
||||||
#
|
#
|
||||||
# @(#)cmv 5.1 (Berkeley) 3/7/91
|
# @(#)cmv 8.2 (Berkeley) 5/4/95
|
||||||
|
# $FreeBSD: src/bin/sh/funcs/cmv,v 1.7 2004/04/06 20:06:53 markm Exp $
|
||||||
|
|
||||||
# Conditional move--don't replace an existing file.
|
# Conditional move--don't replace an existing file.
|
||||||
|
|
||||||
|
@ -47,3 +44,6 @@ cmv() {
|
||||||
fi
|
fi
|
||||||
/bin/mv "$1" "$2"
|
/bin/mv "$1" "$2"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#
|
||||||
|
# $PchId: cmv,v 1.2 2006/03/29 10:43:18 philip Exp $
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
# Copyright (c) 1991 The Regents of the University of California.
|
# Copyright (c) 1991, 1993
|
||||||
# All rights reserved.
|
# The Regents of the University of California. All rights reserved.
|
||||||
#
|
#
|
||||||
# This code is derived from software contributed to Berkeley by
|
# This code is derived from software contributed to Berkeley by
|
||||||
# Kenneth Almquist.
|
# Kenneth Almquist.
|
||||||
|
@ -12,10 +12,6 @@
|
||||||
# 2. Redistributions in binary form must reproduce the above copyright
|
# 2. Redistributions in binary form must reproduce the above copyright
|
||||||
# notice, this list of conditions and the following disclaimer in the
|
# notice, this list of conditions and the following disclaimer in the
|
||||||
# documentation and/or other materials provided with the distribution.
|
# documentation and/or other materials provided with the distribution.
|
||||||
# 3. All advertising materials mentioning features or use of this software
|
|
||||||
# must display the following acknowledgement:
|
|
||||||
# This product includes software developed by the University of
|
|
||||||
# California, Berkeley and its contributors.
|
|
||||||
# 4. Neither the name of the University nor the names of its contributors
|
# 4. Neither the name of the University nor the names of its contributors
|
||||||
# may be used to endorse or promote products derived from this software
|
# may be used to endorse or promote products derived from this software
|
||||||
# without specific prior written permission.
|
# without specific prior written permission.
|
||||||
|
@ -32,7 +28,8 @@
|
||||||
# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||||
# SUCH DAMAGE.
|
# SUCH DAMAGE.
|
||||||
#
|
#
|
||||||
# @(#)dirs 5.1 (Berkeley) 3/7/91
|
# @(#)dirs 8.2 (Berkeley) 5/4/95
|
||||||
|
# $FreeBSD: src/bin/sh/funcs/dirs,v 1.7 2004/04/06 20:06:53 markm Exp $
|
||||||
|
|
||||||
# pushd, popd, and dirs --- written by Chris Bertin
|
# pushd, popd, and dirs --- written by Chris Bertin
|
||||||
# Pixel Computer Inc. ...!wjh12!pixel!pixutl!chris
|
# Pixel Computer Inc. ...!wjh12!pixel!pixutl!chris
|
||||||
|
@ -71,3 +68,6 @@ dirs () {
|
||||||
echo "`pwd` $DSTACK"
|
echo "`pwd` $DSTACK"
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#
|
||||||
|
# $PchId: dirs,v 1.2 2006/03/29 10:43:18 philip Exp $
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
# Copyright (c) 1991 The Regents of the University of California.
|
# Copyright (c) 1991, 1993
|
||||||
# All rights reserved.
|
# The Regents of the University of California. All rights reserved.
|
||||||
#
|
#
|
||||||
# This code is derived from software contributed to Berkeley by
|
# This code is derived from software contributed to Berkeley by
|
||||||
# Kenneth Almquist.
|
# Kenneth Almquist.
|
||||||
|
@ -12,10 +12,6 @@
|
||||||
# 2. Redistributions in binary form must reproduce the above copyright
|
# 2. Redistributions in binary form must reproduce the above copyright
|
||||||
# notice, this list of conditions and the following disclaimer in the
|
# notice, this list of conditions and the following disclaimer in the
|
||||||
# documentation and/or other materials provided with the distribution.
|
# documentation and/or other materials provided with the distribution.
|
||||||
# 3. All advertising materials mentioning features or use of this software
|
|
||||||
# must display the following acknowledgement:
|
|
||||||
# This product includes software developed by the University of
|
|
||||||
# California, Berkeley and its contributors.
|
|
||||||
# 4. Neither the name of the University nor the names of its contributors
|
# 4. Neither the name of the University nor the names of its contributors
|
||||||
# may be used to endorse or promote products derived from this software
|
# may be used to endorse or promote products derived from this software
|
||||||
# without specific prior written permission.
|
# without specific prior written permission.
|
||||||
|
@ -32,7 +28,8 @@
|
||||||
# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||||
# SUCH DAMAGE.
|
# SUCH DAMAGE.
|
||||||
#
|
#
|
||||||
# @(#)kill 5.1 (Berkeley) 3/7/91
|
# @(#)kill 8.2 (Berkeley) 5/4/95
|
||||||
|
# $FreeBSD: src/bin/sh/funcs/kill,v 1.7 2004/04/06 20:06:53 markm Exp $
|
||||||
|
|
||||||
# Convert job names to process ids and then run /bin/kill.
|
# Convert job names to process ids and then run /bin/kill.
|
||||||
|
|
||||||
|
@ -47,3 +44,6 @@ kill() {
|
||||||
done
|
done
|
||||||
/bin/kill $args
|
/bin/kill $args
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#
|
||||||
|
# $PchId: kill,v 1.2 2006/03/29 10:43:18 philip Exp $
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
# Copyright (c) 1991 The Regents of the University of California.
|
# Copyright (c) 1991, 1993
|
||||||
# All rights reserved.
|
# The Regents of the University of California. All rights reserved.
|
||||||
#
|
#
|
||||||
# This code is derived from software contributed to Berkeley by
|
# This code is derived from software contributed to Berkeley by
|
||||||
# Kenneth Almquist.
|
# Kenneth Almquist.
|
||||||
|
@ -12,10 +12,6 @@
|
||||||
# 2. Redistributions in binary form must reproduce the above copyright
|
# 2. Redistributions in binary form must reproduce the above copyright
|
||||||
# notice, this list of conditions and the following disclaimer in the
|
# notice, this list of conditions and the following disclaimer in the
|
||||||
# documentation and/or other materials provided with the distribution.
|
# documentation and/or other materials provided with the distribution.
|
||||||
# 3. All advertising materials mentioning features or use of this software
|
|
||||||
# must display the following acknowledgement:
|
|
||||||
# This product includes software developed by the University of
|
|
||||||
# California, Berkeley and its contributors.
|
|
||||||
# 4. Neither the name of the University nor the names of its contributors
|
# 4. Neither the name of the University nor the names of its contributors
|
||||||
# may be used to endorse or promote products derived from this software
|
# may be used to endorse or promote products derived from this software
|
||||||
# without specific prior written permission.
|
# without specific prior written permission.
|
||||||
|
@ -32,7 +28,11 @@
|
||||||
# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||||
# SUCH DAMAGE.
|
# SUCH DAMAGE.
|
||||||
#
|
#
|
||||||
# @(#)login 5.1 (Berkeley) 3/7/91
|
# @(#)login 8.2 (Berkeley) 5/4/95
|
||||||
|
# $FreeBSD: src/bin/sh/funcs/login,v 1.7 2004/04/06 20:06:53 markm Exp $
|
||||||
|
|
||||||
# replaces the login builtin in the BSD shell
|
# replaces the login builtin in the BSD shell
|
||||||
login () exec login "$@"
|
login () exec login "$@"
|
||||||
|
|
||||||
|
#
|
||||||
|
# $PchId: login,v 1.2 2006/03/29 10:43:18 philip Exp $
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
# Copyright (c) 1991 The Regents of the University of California.
|
# Copyright (c) 1991, 1993
|
||||||
# All rights reserved.
|
# The Regents of the University of California. All rights reserved.
|
||||||
#
|
#
|
||||||
# This code is derived from software contributed to Berkeley by
|
# This code is derived from software contributed to Berkeley by
|
||||||
# Kenneth Almquist.
|
# Kenneth Almquist.
|
||||||
|
@ -12,10 +12,6 @@
|
||||||
# 2. Redistributions in binary form must reproduce the above copyright
|
# 2. Redistributions in binary form must reproduce the above copyright
|
||||||
# notice, this list of conditions and the following disclaimer in the
|
# notice, this list of conditions and the following disclaimer in the
|
||||||
# documentation and/or other materials provided with the distribution.
|
# documentation and/or other materials provided with the distribution.
|
||||||
# 3. All advertising materials mentioning features or use of this software
|
|
||||||
# must display the following acknowledgement:
|
|
||||||
# This product includes software developed by the University of
|
|
||||||
# California, Berkeley and its contributors.
|
|
||||||
# 4. Neither the name of the University nor the names of its contributors
|
# 4. Neither the name of the University nor the names of its contributors
|
||||||
# may be used to endorse or promote products derived from this software
|
# may be used to endorse or promote products derived from this software
|
||||||
# without specific prior written permission.
|
# without specific prior written permission.
|
||||||
|
@ -32,6 +28,10 @@
|
||||||
# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||||
# SUCH DAMAGE.
|
# SUCH DAMAGE.
|
||||||
#
|
#
|
||||||
# @(#)newgrp 5.1 (Berkeley) 3/7/91
|
# @(#)newgrp 8.2 (Berkeley) 5/4/95
|
||||||
|
# $FreeBSD: src/bin/sh/funcs/newgrp,v 1.7 2004/04/06 20:06:53 markm Exp $
|
||||||
|
|
||||||
newgrp() exec newgrp "$@"
|
newgrp() exec newgrp "$@"
|
||||||
|
|
||||||
|
#
|
||||||
|
# $PchId: newgrp,v 1.2 2006/03/29 10:43:18 philip Exp $
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
# Copyright (c) 1991 The Regents of the University of California.
|
# Copyright (c) 1991, 1993
|
||||||
# All rights reserved.
|
# The Regents of the University of California. All rights reserved.
|
||||||
#
|
#
|
||||||
# This code is derived from software contributed to Berkeley by
|
# This code is derived from software contributed to Berkeley by
|
||||||
# Kenneth Almquist.
|
# Kenneth Almquist.
|
||||||
|
@ -12,10 +12,6 @@
|
||||||
# 2. Redistributions in binary form must reproduce the above copyright
|
# 2. Redistributions in binary form must reproduce the above copyright
|
||||||
# notice, this list of conditions and the following disclaimer in the
|
# notice, this list of conditions and the following disclaimer in the
|
||||||
# documentation and/or other materials provided with the distribution.
|
# documentation and/or other materials provided with the distribution.
|
||||||
# 3. All advertising materials mentioning features or use of this software
|
|
||||||
# must display the following acknowledgement:
|
|
||||||
# This product includes software developed by the University of
|
|
||||||
# California, Berkeley and its contributors.
|
|
||||||
# 4. Neither the name of the University nor the names of its contributors
|
# 4. Neither the name of the University nor the names of its contributors
|
||||||
# may be used to endorse or promote products derived from this software
|
# may be used to endorse or promote products derived from this software
|
||||||
# without specific prior written permission.
|
# without specific prior written permission.
|
||||||
|
@ -32,7 +28,8 @@
|
||||||
# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||||
# SUCH DAMAGE.
|
# SUCH DAMAGE.
|
||||||
#
|
#
|
||||||
# @(#)popd 5.1 (Berkeley) 3/7/91
|
# @(#)popd 8.2 (Berkeley) 5/4/95
|
||||||
|
# $FreeBSD: src/bin/sh/funcs/popd,v 1.7 2004/04/06 20:06:53 markm Exp $
|
||||||
|
|
||||||
# pushd, popd, and dirs --- written by Chris Bertin
|
# pushd, popd, and dirs --- written by Chris Bertin
|
||||||
# Pixel Computer Inc. ...!wjh12!pixel!pixutl!chris
|
# Pixel Computer Inc. ...!wjh12!pixel!pixutl!chris
|
||||||
|
@ -71,3 +68,6 @@ dirs () {
|
||||||
echo "`pwd` $DSTACK"
|
echo "`pwd` $DSTACK"
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#
|
||||||
|
# $PchId: popd,v 1.2 2006/03/29 10:43:18 philip Exp $
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
# Copyright (c) 1991 The Regents of the University of California.
|
# Copyright (c) 1991, 1993
|
||||||
# All rights reserved.
|
# The Regents of the University of California. All rights reserved.
|
||||||
#
|
#
|
||||||
# This code is derived from software contributed to Berkeley by
|
# This code is derived from software contributed to Berkeley by
|
||||||
# Kenneth Almquist.
|
# Kenneth Almquist.
|
||||||
|
@ -12,10 +12,6 @@
|
||||||
# 2. Redistributions in binary form must reproduce the above copyright
|
# 2. Redistributions in binary form must reproduce the above copyright
|
||||||
# notice, this list of conditions and the following disclaimer in the
|
# notice, this list of conditions and the following disclaimer in the
|
||||||
# documentation and/or other materials provided with the distribution.
|
# documentation and/or other materials provided with the distribution.
|
||||||
# 3. All advertising materials mentioning features or use of this software
|
|
||||||
# must display the following acknowledgement:
|
|
||||||
# This product includes software developed by the University of
|
|
||||||
# California, Berkeley and its contributors.
|
|
||||||
# 4. Neither the name of the University nor the names of its contributors
|
# 4. Neither the name of the University nor the names of its contributors
|
||||||
# may be used to endorse or promote products derived from this software
|
# may be used to endorse or promote products derived from this software
|
||||||
# without specific prior written permission.
|
# without specific prior written permission.
|
||||||
|
@ -32,7 +28,8 @@
|
||||||
# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||||
# SUCH DAMAGE.
|
# SUCH DAMAGE.
|
||||||
#
|
#
|
||||||
# @(#)pushd 5.1 (Berkeley) 3/7/91
|
# @(#)pushd 8.2 (Berkeley) 5/4/95
|
||||||
|
# $FreeBSD: src/bin/sh/funcs/pushd,v 1.7 2004/04/06 20:06:53 markm Exp $
|
||||||
|
|
||||||
# pushd, popd, and dirs --- written by Chris Bertin
|
# pushd, popd, and dirs --- written by Chris Bertin
|
||||||
# Pixel Computer Inc. ...!wjh12!pixel!pixutl!chris
|
# Pixel Computer Inc. ...!wjh12!pixel!pixutl!chris
|
||||||
|
@ -71,3 +68,6 @@ dirs () {
|
||||||
echo "`pwd` $DSTACK"
|
echo "`pwd` $DSTACK"
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#
|
||||||
|
# $PchId: pushd,v 1.2 2006/03/29 10:43:18 philip Exp $
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
# Copyright (c) 1991 The Regents of the University of California.
|
# Copyright (c) 1991, 1993
|
||||||
# All rights reserved.
|
# The Regents of the University of California. All rights reserved.
|
||||||
#
|
#
|
||||||
# This code is derived from software contributed to Berkeley by
|
# This code is derived from software contributed to Berkeley by
|
||||||
# Kenneth Almquist.
|
# Kenneth Almquist.
|
||||||
|
@ -12,10 +12,6 @@
|
||||||
# 2. Redistributions in binary form must reproduce the above copyright
|
# 2. Redistributions in binary form must reproduce the above copyright
|
||||||
# notice, this list of conditions and the following disclaimer in the
|
# notice, this list of conditions and the following disclaimer in the
|
||||||
# documentation and/or other materials provided with the distribution.
|
# documentation and/or other materials provided with the distribution.
|
||||||
# 3. All advertising materials mentioning features or use of this software
|
|
||||||
# must display the following acknowledgement:
|
|
||||||
# This product includes software developed by the University of
|
|
||||||
# California, Berkeley and its contributors.
|
|
||||||
# 4. Neither the name of the University nor the names of its contributors
|
# 4. Neither the name of the University nor the names of its contributors
|
||||||
# may be used to endorse or promote products derived from this software
|
# may be used to endorse or promote products derived from this software
|
||||||
# without specific prior written permission.
|
# without specific prior written permission.
|
||||||
|
@ -32,10 +28,14 @@
|
||||||
# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||||
# SUCH DAMAGE.
|
# SUCH DAMAGE.
|
||||||
#
|
#
|
||||||
# @(#)suspend 5.1 (Berkeley) 3/7/91
|
# @(#)suspend 8.2 (Berkeley) 5/4/95
|
||||||
|
# $FreeBSD: src/bin/sh/funcs/suspend,v 1.7 2004/04/06 20:06:53 markm Exp $
|
||||||
|
|
||||||
suspend() {
|
suspend() {
|
||||||
local -
|
local -
|
||||||
set +j
|
set +j
|
||||||
kill -TSTP 0
|
kill -TSTP 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#
|
||||||
|
# $PchId: suspend,v 1.2 2006/03/29 10:43:18 philip Exp $
|
||||||
|
|
533
commands/ash/histedit.c
Normal file
533
commands/ash/histedit.c
Normal file
|
@ -0,0 +1,533 @@
|
||||||
|
/*-
|
||||||
|
* Copyright (c) 1993
|
||||||
|
* The Regents of the University of California. All rights reserved.
|
||||||
|
*
|
||||||
|
* This code is derived from software contributed to Berkeley by
|
||||||
|
* Kenneth Almquist.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
* 1. Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* 4. Neither the name of the University nor the names of its contributors
|
||||||
|
* may be used to endorse or promote products derived from this software
|
||||||
|
* without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||||
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||||
|
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
|
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||||
|
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||||
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||||
|
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||||
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||||
|
* SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef lint
|
||||||
|
#if 0
|
||||||
|
static char sccsid[] = "@(#)histedit.c 8.2 (Berkeley) 5/4/95";
|
||||||
|
#endif
|
||||||
|
#endif /* not lint */
|
||||||
|
/*
|
||||||
|
#include <sys/cdefs.h>
|
||||||
|
__FBSDID("$FreeBSD: src/bin/sh/histedit.c,v 1.26 2004/04/06 20:06:51 markm Exp $");
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <limits.h>
|
||||||
|
#ifndef NO_PATHS_H
|
||||||
|
#include <paths.h>
|
||||||
|
#endif
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
/*
|
||||||
|
* Editline and history functions (and glue).
|
||||||
|
*/
|
||||||
|
#include "shell.h"
|
||||||
|
#include "parser.h"
|
||||||
|
#include "var.h"
|
||||||
|
#include "options.h"
|
||||||
|
#include "main.h"
|
||||||
|
#include "output.h"
|
||||||
|
#include "mystring.h"
|
||||||
|
#include "builtins.h"
|
||||||
|
#if !defined(NO_HISTORY) && !defined(EDITLINE)
|
||||||
|
#include "myhistedit.h"
|
||||||
|
#include "complete.h"
|
||||||
|
#include "error.h"
|
||||||
|
#include "eval.h"
|
||||||
|
#include "memalloc.h"
|
||||||
|
|
||||||
|
#define MAXHISTLOOPS 4 /* max recursions through fc */
|
||||||
|
#define DEFEDITOR "ed" /* default editor *should* be $EDITOR */
|
||||||
|
|
||||||
|
History *hist; /* history cookie */
|
||||||
|
EditLine *el; /* editline cookie */
|
||||||
|
int displayhist;
|
||||||
|
static FILE *el_in, *el_out, *el_err;
|
||||||
|
|
||||||
|
STATIC char *fc_replace(const char *, char *, char *);
|
||||||
|
STATIC int not_fcnumber(char *);
|
||||||
|
STATIC int str_to_event(char *, int);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Set history and editing status. Called whenever the status may
|
||||||
|
* have changed (figures out what to do).
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
histedit(void)
|
||||||
|
{
|
||||||
|
|
||||||
|
#define editing (Eflag || Vflag)
|
||||||
|
|
||||||
|
if (iflag) {
|
||||||
|
if (!hist) {
|
||||||
|
/*
|
||||||
|
* turn history on
|
||||||
|
*/
|
||||||
|
INTOFF;
|
||||||
|
hist = history_init();
|
||||||
|
INTON;
|
||||||
|
|
||||||
|
if (hist != NULL)
|
||||||
|
sethistsize(histsizeval());
|
||||||
|
else
|
||||||
|
out2str("sh: can't initialize history\n");
|
||||||
|
}
|
||||||
|
if (editing && !el && isatty(0)) { /* && isatty(2) ??? */
|
||||||
|
/*
|
||||||
|
* turn editing on
|
||||||
|
*/
|
||||||
|
INTOFF;
|
||||||
|
if (el_in == NULL)
|
||||||
|
el_in = fdopen(0, "r");
|
||||||
|
if (el_err == NULL)
|
||||||
|
el_err = fdopen(1, "w");
|
||||||
|
if (el_out == NULL)
|
||||||
|
el_out = fdopen(2, "w");
|
||||||
|
if (el_in == NULL || el_err == NULL || el_out == NULL)
|
||||||
|
goto bad;
|
||||||
|
el = el_init(arg0, el_in, el_out, el_err);
|
||||||
|
if (el != NULL) {
|
||||||
|
if (hist)
|
||||||
|
el_set(el, EL_HIST, history, hist);
|
||||||
|
el_set(el, EL_PROMPT, getprompt);
|
||||||
|
} else {
|
||||||
|
bad:
|
||||||
|
out2str("sh: can't initialize editing\n");
|
||||||
|
}
|
||||||
|
INTON;
|
||||||
|
} else if (!editing && el) {
|
||||||
|
INTOFF;
|
||||||
|
el_end(el);
|
||||||
|
el = NULL;
|
||||||
|
INTON;
|
||||||
|
}
|
||||||
|
if (el) {
|
||||||
|
if (Vflag)
|
||||||
|
el_set(el, EL_EDITOR, "vi");
|
||||||
|
else if (Eflag)
|
||||||
|
el_set(el, EL_EDITOR, "emacs");
|
||||||
|
el_set(el, EL_ADDFN, "ed-do-complete",
|
||||||
|
"Complete Argument", complete);
|
||||||
|
el_set(el, EL_ADDFN, "ed-list-complete",
|
||||||
|
"List Argument Completions", complete_list);
|
||||||
|
el_set(el, EL_ADDFN, "ed-maybe-complete",
|
||||||
|
"Complete Argument Or List Completions",
|
||||||
|
complete_or_list);
|
||||||
|
el_set(el, EL_ADDFN, "ed-expand",
|
||||||
|
"Expand Completions", complete_expand);
|
||||||
|
el_set(el, EL_BIND, "^I", "ed-maybe-complete", NULL);
|
||||||
|
el_set(el, EL_BIND, "-a", "=", "ed-list-complete",
|
||||||
|
NULL);
|
||||||
|
el_set(el, EL_BIND, "-a", "\\\\", "ed-do-complete",
|
||||||
|
NULL);
|
||||||
|
el_set(el, EL_BIND, "-a", "*", "ed-expand",
|
||||||
|
NULL);
|
||||||
|
el_source(el, NULL);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
INTOFF;
|
||||||
|
if (el) { /* no editing if not interactive */
|
||||||
|
el_end(el);
|
||||||
|
el = NULL;
|
||||||
|
}
|
||||||
|
if (hist) {
|
||||||
|
history_end(hist);
|
||||||
|
hist = NULL;
|
||||||
|
}
|
||||||
|
INTON;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
sethistsize(hs)
|
||||||
|
const char *hs;
|
||||||
|
{
|
||||||
|
int histsize;
|
||||||
|
HistEvent he;
|
||||||
|
|
||||||
|
if (hist != NULL) {
|
||||||
|
if (hs == NULL || *hs == '\0' ||
|
||||||
|
(histsize = atoi(hs)) < 0)
|
||||||
|
histsize = 100;
|
||||||
|
history(hist, &he, H_EVENT, histsize);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
histcmd(int argc, char **argv)
|
||||||
|
{
|
||||||
|
int ch;
|
||||||
|
char *editor = NULL;
|
||||||
|
HistEvent he;
|
||||||
|
int lflg = 0, nflg = 0, rflg = 0, sflg = 0;
|
||||||
|
int i, retval;
|
||||||
|
char *firststr, *laststr;
|
||||||
|
int first, last, direction;
|
||||||
|
char *pat = NULL, *repl;
|
||||||
|
static int active = 0;
|
||||||
|
struct jmploc jmploc;
|
||||||
|
struct jmploc *volatile savehandler;
|
||||||
|
char editfile[PATH_MAX];
|
||||||
|
FILE *efp;
|
||||||
|
int oldhistnum;
|
||||||
|
#ifdef __GNUC__
|
||||||
|
/* Avoid longjmp clobbering */
|
||||||
|
(void) &editor;
|
||||||
|
(void) &lflg;
|
||||||
|
(void) &nflg;
|
||||||
|
(void) &rflg;
|
||||||
|
(void) &sflg;
|
||||||
|
(void) &firststr;
|
||||||
|
(void) &laststr;
|
||||||
|
(void) &pat;
|
||||||
|
(void) &repl;
|
||||||
|
(void) &efp;
|
||||||
|
(void) &argc;
|
||||||
|
(void) &argv;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (hist == NULL)
|
||||||
|
error("history not active");
|
||||||
|
|
||||||
|
if (argc == 1)
|
||||||
|
error("missing history argument");
|
||||||
|
|
||||||
|
optreset = 1; optind = 1; /* initialize getopt */
|
||||||
|
opterr = 0;
|
||||||
|
while (not_fcnumber(argv[optind]) &&
|
||||||
|
(ch = getopt(argc, argv, ":e:lnrs")) != -1)
|
||||||
|
switch ((char)ch) {
|
||||||
|
case 'e':
|
||||||
|
editor = optarg;
|
||||||
|
break;
|
||||||
|
case 'l':
|
||||||
|
lflg = 1;
|
||||||
|
break;
|
||||||
|
case 'n':
|
||||||
|
nflg = 1;
|
||||||
|
break;
|
||||||
|
case 'r':
|
||||||
|
rflg = 1;
|
||||||
|
break;
|
||||||
|
case 's':
|
||||||
|
sflg = 1;
|
||||||
|
break;
|
||||||
|
case ':':
|
||||||
|
error("option -%c expects argument", optopt);
|
||||||
|
case '?':
|
||||||
|
default:
|
||||||
|
error("unknown option: -%c", optopt);
|
||||||
|
}
|
||||||
|
argc -= optind, argv += optind;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If executing...
|
||||||
|
*/
|
||||||
|
if (lflg == 0 || editor || sflg) {
|
||||||
|
lflg = 0; /* ignore */
|
||||||
|
editfile[0] = '\0';
|
||||||
|
/*
|
||||||
|
* Catch interrupts to reset active counter and
|
||||||
|
* cleanup temp files.
|
||||||
|
*/
|
||||||
|
if (setjmp(jmploc.loc)) {
|
||||||
|
active = 0;
|
||||||
|
if (*editfile)
|
||||||
|
unlink(editfile);
|
||||||
|
handler = savehandler;
|
||||||
|
longjmp(handler->loc, 1);
|
||||||
|
}
|
||||||
|
savehandler = handler;
|
||||||
|
handler = &jmploc;
|
||||||
|
if (++active > MAXHISTLOOPS) {
|
||||||
|
active = 0;
|
||||||
|
displayhist = 0;
|
||||||
|
error("called recursively too many times");
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
* Set editor.
|
||||||
|
*/
|
||||||
|
if (sflg == 0) {
|
||||||
|
if (editor == NULL &&
|
||||||
|
(editor = bltinlookup("FCEDIT", 1)) == NULL &&
|
||||||
|
(editor = bltinlookup("EDITOR", 1)) == NULL)
|
||||||
|
editor = DEFEDITOR;
|
||||||
|
if (editor[0] == '-' && editor[1] == '\0') {
|
||||||
|
sflg = 1; /* no edit */
|
||||||
|
editor = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If executing, parse [old=new] now
|
||||||
|
*/
|
||||||
|
if (lflg == 0 && argc > 0 &&
|
||||||
|
((repl = strchr(argv[0], '=')) != NULL)) {
|
||||||
|
pat = argv[0];
|
||||||
|
*repl++ = '\0';
|
||||||
|
argc--, argv++;
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
* determine [first] and [last]
|
||||||
|
*/
|
||||||
|
switch (argc) {
|
||||||
|
case 0:
|
||||||
|
firststr = lflg ? "-16" : "-1";
|
||||||
|
laststr = "-1";
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
firststr = argv[0];
|
||||||
|
laststr = lflg ? "-1" : argv[0];
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
firststr = argv[0];
|
||||||
|
laststr = argv[1];
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
error("too many args");
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
* Turn into event numbers.
|
||||||
|
*/
|
||||||
|
first = str_to_event(firststr, 0);
|
||||||
|
last = str_to_event(laststr, 1);
|
||||||
|
|
||||||
|
if (rflg) {
|
||||||
|
i = last;
|
||||||
|
last = first;
|
||||||
|
first = i;
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
* XXX - this should not depend on the event numbers
|
||||||
|
* always increasing. Add sequence numbers or offset
|
||||||
|
* to the history element in next (diskbased) release.
|
||||||
|
*/
|
||||||
|
direction = first < last ? H_PREV : H_NEXT;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If editing, grab a temp file.
|
||||||
|
*/
|
||||||
|
if (editor) {
|
||||||
|
int fd;
|
||||||
|
INTOFF; /* easier */
|
||||||
|
sprintf(editfile, "%s/_shXXXXXX", _PATH_TMP);
|
||||||
|
if ((fd = mkstemp(editfile)) < 0)
|
||||||
|
error("can't create temporary file %s", editfile);
|
||||||
|
if ((efp = fdopen(fd, "w")) == NULL) {
|
||||||
|
close(fd);
|
||||||
|
error("can't allocate stdio buffer for temp");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Loop through selected history events. If listing or executing,
|
||||||
|
* do it now. Otherwise, put into temp file and call the editor
|
||||||
|
* after.
|
||||||
|
*
|
||||||
|
* The history interface needs rethinking, as the following
|
||||||
|
* convolutions will demonstrate.
|
||||||
|
*/
|
||||||
|
history(hist, &he, H_FIRST);
|
||||||
|
retval = history(hist, &he, H_NEXT_EVENT, first);
|
||||||
|
for (;retval != -1; retval = history(hist, &he, direction)) {
|
||||||
|
if (lflg) {
|
||||||
|
if (!nflg)
|
||||||
|
out1fmt("%5d ", he.num);
|
||||||
|
out1str(he.str);
|
||||||
|
} else {
|
||||||
|
char *s = pat ?
|
||||||
|
fc_replace(he.str, pat, repl) : (char *)he.str;
|
||||||
|
|
||||||
|
if (sflg) {
|
||||||
|
if (displayhist) {
|
||||||
|
out2str(s);
|
||||||
|
}
|
||||||
|
evalstring(s);
|
||||||
|
if (displayhist && hist) {
|
||||||
|
/*
|
||||||
|
* XXX what about recursive and
|
||||||
|
* relative histnums.
|
||||||
|
*/
|
||||||
|
oldhistnum = he.num;
|
||||||
|
history(hist, &he, H_ENTER, s);
|
||||||
|
/*
|
||||||
|
* XXX H_ENTER moves the internal
|
||||||
|
* cursor, set it back to the current
|
||||||
|
* entry.
|
||||||
|
*/
|
||||||
|
retval = history(hist, &he,
|
||||||
|
H_NEXT_EVENT, oldhistnum);
|
||||||
|
}
|
||||||
|
} else
|
||||||
|
fputs(s, efp);
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
* At end? (if we were to loose last, we'd sure be
|
||||||
|
* messed up).
|
||||||
|
*/
|
||||||
|
if (he.num == last)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (editor) {
|
||||||
|
char *editcmd;
|
||||||
|
|
||||||
|
fclose(efp);
|
||||||
|
editcmd = stalloc(strlen(editor) + strlen(editfile) + 2);
|
||||||
|
sprintf(editcmd, "%s %s", editor, editfile);
|
||||||
|
evalstring(editcmd); /* XXX - should use no JC command */
|
||||||
|
INTON;
|
||||||
|
readcmdfile(editfile); /* XXX - should read back - quick tst */
|
||||||
|
unlink(editfile);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (lflg == 0 && active > 0)
|
||||||
|
--active;
|
||||||
|
if (displayhist)
|
||||||
|
displayhist = 0;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
STATIC char *
|
||||||
|
fc_replace(const char *s, char *p, char *r)
|
||||||
|
{
|
||||||
|
char *dest;
|
||||||
|
int plen = strlen(p);
|
||||||
|
|
||||||
|
STARTSTACKSTR(dest);
|
||||||
|
while (*s) {
|
||||||
|
if (*s == *p && strncmp(s, p, plen) == 0) {
|
||||||
|
while (*r)
|
||||||
|
STPUTC(*r++, dest);
|
||||||
|
s += plen;
|
||||||
|
*p = '\0'; /* so no more matches */
|
||||||
|
} else
|
||||||
|
STPUTC(*s++, dest);
|
||||||
|
}
|
||||||
|
STACKSTRNUL(dest);
|
||||||
|
dest = grabstackstr(dest);
|
||||||
|
|
||||||
|
return (dest);
|
||||||
|
}
|
||||||
|
|
||||||
|
STATIC int
|
||||||
|
not_fcnumber(char *s)
|
||||||
|
{
|
||||||
|
if (s == NULL)
|
||||||
|
return (0);
|
||||||
|
if (*s == '-')
|
||||||
|
s++;
|
||||||
|
return (!is_number(s));
|
||||||
|
}
|
||||||
|
|
||||||
|
STATIC int
|
||||||
|
str_to_event(char *str, int last)
|
||||||
|
{
|
||||||
|
HistEvent he;
|
||||||
|
char *s = str;
|
||||||
|
int relative = 0;
|
||||||
|
int i, retval;
|
||||||
|
|
||||||
|
retval = history(hist, &he, H_FIRST);
|
||||||
|
switch (*s) {
|
||||||
|
case '-':
|
||||||
|
relative = 1;
|
||||||
|
/*FALLTHROUGH*/
|
||||||
|
case '+':
|
||||||
|
s++;
|
||||||
|
}
|
||||||
|
if (is_number(s)) {
|
||||||
|
i = atoi(s);
|
||||||
|
if (relative) {
|
||||||
|
while (retval != -1 && i--) {
|
||||||
|
retval = history(hist, &he, H_NEXT);
|
||||||
|
}
|
||||||
|
if (retval == -1)
|
||||||
|
retval = history(hist, &he, H_LAST);
|
||||||
|
} else {
|
||||||
|
retval = history(hist, &he, H_NEXT_EVENT, i);
|
||||||
|
if (retval == -1) {
|
||||||
|
/*
|
||||||
|
* the notion of first and last is
|
||||||
|
* backwards to that of the history package
|
||||||
|
*/
|
||||||
|
retval = history(hist, &he, last ? H_FIRST : H_LAST);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (retval == -1)
|
||||||
|
error("history number %s not found (internal error)",
|
||||||
|
str);
|
||||||
|
} else {
|
||||||
|
/*
|
||||||
|
* pattern
|
||||||
|
*/
|
||||||
|
retval = history(hist, &he, H_PREV_STR, str);
|
||||||
|
if (retval == -1)
|
||||||
|
error("history pattern not found: %s", str);
|
||||||
|
}
|
||||||
|
return (he.num);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
bindcmd(int argc, char **argv)
|
||||||
|
{
|
||||||
|
|
||||||
|
if (el == NULL)
|
||||||
|
error("line editing is disabled");
|
||||||
|
return (el_parse(el, argc, argv));
|
||||||
|
}
|
||||||
|
|
||||||
|
#else
|
||||||
|
#include "error.h"
|
||||||
|
|
||||||
|
int
|
||||||
|
histcmd(int argc, char **argv)
|
||||||
|
{
|
||||||
|
|
||||||
|
error("not compiled with history support");
|
||||||
|
/*NOTREACHED*/
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
bindcmd(int argc, char **argv)
|
||||||
|
{
|
||||||
|
|
||||||
|
error("not compiled with line editing support");
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
#endif /* !NO_HISTORY && !EDITLINE */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* $PchId: histedit.c,v 1.6 2006/04/10 14:52:58 philip Exp $
|
||||||
|
*/
|
|
@ -1,6 +1,6 @@
|
||||||
/*-
|
/*-
|
||||||
* Copyright (c) 1991 The Regents of the University of California.
|
* Copyright (c) 1991, 1993
|
||||||
* All rights reserved.
|
* The Regents of the University of California. All rights reserved.
|
||||||
*
|
*
|
||||||
* This code is derived from software contributed to Berkeley by
|
* This code is derived from software contributed to Berkeley by
|
||||||
* Kenneth Almquist.
|
* Kenneth Almquist.
|
||||||
|
@ -13,10 +13,6 @@
|
||||||
* 2. Redistributions in binary form must reproduce the above copyright
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
* notice, this list of conditions and the following disclaimer in the
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
* documentation and/or other materials provided with the distribution.
|
* documentation and/or other materials provided with the distribution.
|
||||||
* 3. All advertising materials mentioning features or use of this software
|
|
||||||
* must display the following acknowledgement:
|
|
||||||
* This product includes software developed by the University of
|
|
||||||
* California, Berkeley and its contributors.
|
|
||||||
* 4. Neither the name of the University nor the names of its contributors
|
* 4. Neither the name of the University nor the names of its contributors
|
||||||
* may be used to endorse or promote products derived from this software
|
* may be used to endorse or promote products derived from this software
|
||||||
* without specific prior written permission.
|
* without specific prior written permission.
|
||||||
|
@ -33,15 +29,14 @@
|
||||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||||
* SUCH DAMAGE.
|
* SUCH DAMAGE.
|
||||||
*
|
*
|
||||||
* @(#)init.h 5.1 (Berkeley) 3/7/91
|
* @(#)init.h 8.2 (Berkeley) 5/4/95
|
||||||
|
* $FreeBSD: src/bin/sh/init.h,v 1.8 2004/04/06 20:06:51 markm Exp $
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifdef __STDC__
|
|
||||||
void init(void);
|
void init(void);
|
||||||
void reset(void);
|
void reset(void);
|
||||||
void initshellproc(void);
|
void initshellproc(void);
|
||||||
#else
|
|
||||||
void init();
|
/*
|
||||||
void reset();
|
* $PchId: init.h,v 1.3 2006/03/30 14:31:06 philip Exp $
|
||||||
void initshellproc();
|
*/
|
||||||
#endif
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/*-
|
/*-
|
||||||
* Copyright (c) 1991 The Regents of the University of California.
|
* Copyright (c) 1991, 1993
|
||||||
* All rights reserved.
|
* The Regents of the University of California. All rights reserved.
|
||||||
*
|
*
|
||||||
* This code is derived from software contributed to Berkeley by
|
* This code is derived from software contributed to Berkeley by
|
||||||
* Kenneth Almquist.
|
* Kenneth Almquist.
|
||||||
|
@ -13,10 +13,6 @@
|
||||||
* 2. Redistributions in binary form must reproduce the above copyright
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
* notice, this list of conditions and the following disclaimer in the
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
* documentation and/or other materials provided with the distribution.
|
* documentation and/or other materials provided with the distribution.
|
||||||
* 3. All advertising materials mentioning features or use of this software
|
|
||||||
* must display the following acknowledgement:
|
|
||||||
* This product includes software developed by the University of
|
|
||||||
* California, Berkeley and its contributors.
|
|
||||||
* 4. Neither the name of the University nor the names of its contributors
|
* 4. Neither the name of the University nor the names of its contributors
|
||||||
* may be used to endorse or promote products derived from this software
|
* may be used to endorse or promote products derived from this software
|
||||||
* without specific prior written permission.
|
* without specific prior written permission.
|
||||||
|
@ -35,26 +31,61 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef lint
|
#ifndef lint
|
||||||
static char sccsid[] = "@(#)input.c 5.4 (Berkeley) 7/1/91";
|
#if 0
|
||||||
|
static char sccsid[] = "@(#)input.c 8.3 (Berkeley) 6/9/95";
|
||||||
|
#endif
|
||||||
#endif /* not lint */
|
#endif /* not lint */
|
||||||
|
/*
|
||||||
|
#include <sys/cdefs.h>
|
||||||
|
__FBSDID("$FreeBSD: src/bin/sh/input.c,v 1.22 2004/04/06 20:06:51 markm Exp $");
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <stdio.h> /* defines BUFSIZ */
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This file implements the input routines used by the parser.
|
* This file implements the input routines used by the parser.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <sys/types.h>
|
|
||||||
#include <stdio.h> /* defines BUFSIZ */
|
|
||||||
#include "shell.h"
|
#include "shell.h"
|
||||||
#include <fcntl.h>
|
#include "redir.h"
|
||||||
#include <errno.h>
|
|
||||||
#include "syntax.h"
|
#include "syntax.h"
|
||||||
#include "input.h"
|
#include "input.h"
|
||||||
#include "output.h"
|
#include "output.h"
|
||||||
|
#include "options.h"
|
||||||
#include "memalloc.h"
|
#include "memalloc.h"
|
||||||
#include "error.h"
|
#include "error.h"
|
||||||
|
#include "alias.h"
|
||||||
|
#include "parser.h"
|
||||||
|
#ifdef EDITLINE
|
||||||
|
#ifdef __minix_vmd
|
||||||
|
#include <readline/readline.h>
|
||||||
|
#else
|
||||||
|
/* What about other systems? */
|
||||||
|
#endif
|
||||||
|
#else
|
||||||
|
#include "myhistedit.h"
|
||||||
|
#endif
|
||||||
|
#include "redir.h"
|
||||||
|
#include "trap.h"
|
||||||
|
|
||||||
|
static void popstring(void);
|
||||||
|
|
||||||
#define EOF_NLEFT -99 /* value of parsenleft when EOF pushed back */
|
#define EOF_NLEFT -99 /* value of parsenleft when EOF pushed back */
|
||||||
|
|
||||||
|
MKINIT
|
||||||
|
struct strpush {
|
||||||
|
struct strpush *prev; /* preceding string on stack */
|
||||||
|
char *prevstring;
|
||||||
|
int prevnleft;
|
||||||
|
int prevlleft;
|
||||||
|
struct alias *ap; /* if push was associated with an alias */
|
||||||
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The parsefile structure pointed to by the global variable parsefile
|
* The parsefile structure pointed to by the global variable parsefile
|
||||||
|
@ -63,36 +94,34 @@ static char sccsid[] = "@(#)input.c 5.4 (Berkeley) 7/1/91";
|
||||||
|
|
||||||
MKINIT
|
MKINIT
|
||||||
struct parsefile {
|
struct parsefile {
|
||||||
|
struct parsefile *prev; /* preceding file on stack */
|
||||||
int linno; /* current line */
|
int linno; /* current line */
|
||||||
int fd; /* file descriptor (or -1 if string) */
|
int fd; /* file descriptor (or -1 if string) */
|
||||||
int nleft; /* number of chars left in buffer */
|
int nleft; /* number of chars left in this line */
|
||||||
|
int lleft; /* number of lines left in this buffer */
|
||||||
char *nextc; /* next char in buffer */
|
char *nextc; /* next char in buffer */
|
||||||
struct parsefile *prev; /* preceding file on stack */
|
|
||||||
char *buf; /* input buffer */
|
char *buf; /* input buffer */
|
||||||
|
struct strpush *strpush; /* for pushing strings at this level */
|
||||||
|
struct strpush basestrpush; /* so pushing one is fast */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
int plinno = 1; /* input line number */
|
int plinno = 1; /* input line number */
|
||||||
MKINIT int parsenleft; /* copy of parsefile->nleft */
|
MKINIT int parsenleft; /* copy of parsefile->nleft */
|
||||||
|
MKINIT int parselleft; /* copy of parsefile->lleft */
|
||||||
char *parsenextc; /* copy of parsefile->nextc */
|
char *parsenextc; /* copy of parsefile->nextc */
|
||||||
MKINIT struct parsefile basepf; /* top level input file */
|
MKINIT struct parsefile basepf; /* top level input file */
|
||||||
char basebuf[BUFSIZ]; /* buffer for top level input file */
|
char basebuf[BUFSIZ]; /* buffer for top level input file */
|
||||||
struct parsefile *parsefile = &basepf; /* current input file */
|
STATIC struct parsefile *parsefile = &basepf; /* current input file */
|
||||||
char *pushedstring; /* copy of parsenextc when text pushed back */
|
int init_editline = 0; /* editline library initialized? */
|
||||||
int pushednleft; /* copy of parsenleft when text pushed back */
|
int whichprompt; /* -1 == PSE, 1 == PS1, 2 == PS2 */
|
||||||
|
|
||||||
#if READLINE
|
#ifndef EDITLINE
|
||||||
char *readline __P((const char *prompt));
|
EditLine *el; /* cookie for editline package */
|
||||||
char *r_use_prompt = NULL; /* the prompt to use with readline */
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef __STDC__
|
|
||||||
STATIC void pushfile(void);
|
STATIC void pushfile(void);
|
||||||
#else
|
static int preadfd(void);
|
||||||
STATIC void pushfile();
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef mkinit
|
#ifdef mkinit
|
||||||
INCLUDE "input.h"
|
INCLUDE "input.h"
|
||||||
|
@ -106,7 +135,7 @@ INIT {
|
||||||
|
|
||||||
RESET {
|
RESET {
|
||||||
if (exception != EXSHELLPROC)
|
if (exception != EXSHELLPROC)
|
||||||
parsenleft = 0; /* clear input buffer */
|
parselleft = parsenleft = 0; /* clear input buffer */
|
||||||
popallfiles();
|
popallfiles();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -121,10 +150,9 @@ SHELLPROC {
|
||||||
*/
|
*/
|
||||||
|
|
||||||
char *
|
char *
|
||||||
pfgets(line, len)
|
pfgets(char *line, int len)
|
||||||
char *line;
|
|
||||||
{
|
{
|
||||||
register char *p = line;
|
char *p = line;
|
||||||
int nleft = len;
|
int nleft = len;
|
||||||
int c;
|
int c;
|
||||||
|
|
||||||
|
@ -151,64 +179,74 @@ pfgets(line, len)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int
|
int
|
||||||
pgetc() {
|
pgetc(void)
|
||||||
|
{
|
||||||
return pgetc_macro();
|
return pgetc_macro();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
static int
|
||||||
* Refill the input buffer and return the next input character:
|
preadfd(void)
|
||||||
*
|
{
|
||||||
* 1) If a string was pushed back on the input, switch back to the regular
|
int nr;
|
||||||
* buffer.
|
parsenextc = parsefile->buf;
|
||||||
* 2) If an EOF was pushed back (parsenleft == EOF_NLEFT) or we are reading
|
|
||||||
* from a string so we can't refill the buffer, return EOF.
|
|
||||||
* 3) Call read to read in the characters.
|
|
||||||
* 4) Delete all nul characters from the buffer.
|
|
||||||
*/
|
|
||||||
|
|
||||||
int
|
#if !defined(NO_HISTORY) && !defined(EDITLINE)
|
||||||
preadbuffer() {
|
if (el != NULL && gotwinch) {
|
||||||
register char *p, *q;
|
gotwinch = 0;
|
||||||
register int i;
|
el_resize(el);
|
||||||
|
|
||||||
if (pushedstring) {
|
|
||||||
parsenextc = pushedstring;
|
|
||||||
pushedstring = NULL;
|
|
||||||
parsenleft = pushednleft;
|
|
||||||
if (--parsenleft >= 0)
|
|
||||||
return *parsenextc++;
|
|
||||||
}
|
}
|
||||||
if (parsenleft == EOF_NLEFT || parsefile->buf == NULL)
|
|
||||||
return PEOF;
|
|
||||||
flushout(&output);
|
|
||||||
flushout(&errout);
|
|
||||||
#if READLINE
|
|
||||||
/* Use the readline() call if a prompt is to be printed (interactive). */
|
|
||||||
if (r_use_prompt != NULL) {
|
|
||||||
char *prompt;
|
|
||||||
char *line;
|
|
||||||
|
|
||||||
p = parsenextc = parsefile->buf;
|
|
||||||
|
|
||||||
prompt = r_use_prompt;
|
|
||||||
r_use_prompt = NULL;
|
|
||||||
|
|
||||||
if ((line = readline(prompt)) == NULL) {
|
|
||||||
parsenleft = EOF_NLEFT;
|
|
||||||
return PEOF;
|
|
||||||
}
|
|
||||||
strcpy(p, line);
|
|
||||||
free(line);
|
|
||||||
i = strlen(p);
|
|
||||||
p[i++] = '\n';
|
|
||||||
} else {
|
|
||||||
#endif
|
#endif
|
||||||
retry:
|
retry:
|
||||||
p = parsenextc = parsefile->buf;
|
#ifndef NO_HISTORY
|
||||||
i = read(parsefile->fd, p, BUFSIZ);
|
#ifdef EDITLINE
|
||||||
if (i <= 0) {
|
if (parsefile->fd == 0) {
|
||||||
if (i < 0) {
|
static const char *rl_cp= NULL;
|
||||||
|
static size_t rl_off= 0;
|
||||||
|
|
||||||
|
if (!rl_cp)
|
||||||
|
{
|
||||||
|
rl_cp = readline(getprompt(NULL));
|
||||||
|
if (rl_cp == NULL)
|
||||||
|
nr = 0;
|
||||||
|
}
|
||||||
|
if (rl_cp)
|
||||||
|
{
|
||||||
|
nr= strlen(rl_cp+rl_off);
|
||||||
|
if (nr >= BUFSIZ-1)
|
||||||
|
{
|
||||||
|
nr= BUFSIZ-1;
|
||||||
|
(void) memcpy(parsenextc, rl_cp+rl_off, nr);
|
||||||
|
rl_off += nr;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
(void) memcpy(parsenextc, rl_cp+rl_off, nr);
|
||||||
|
parsenextc[nr++]= '\n';
|
||||||
|
free(rl_cp);
|
||||||
|
rl_cp= NULL;
|
||||||
|
rl_off= 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else
|
||||||
|
#else /* !EDITLINE */
|
||||||
|
if (parsefile->fd == 0 && el) {
|
||||||
|
const char *rl_cp;
|
||||||
|
|
||||||
|
rl_cp = el_gets(el, &nr);
|
||||||
|
if (rl_cp == NULL)
|
||||||
|
nr = 0;
|
||||||
|
else {
|
||||||
|
/* XXX - BUFSIZE should redesign so not necessary */
|
||||||
|
(void) strcpy(parsenextc, rl_cp);
|
||||||
|
}
|
||||||
|
} else
|
||||||
|
#endif /* !EDITLINE */
|
||||||
|
#endif
|
||||||
|
nr = read(parsefile->fd, parsenextc, BUFSIZ - 1);
|
||||||
|
|
||||||
|
if (nr <= 0) {
|
||||||
|
if (nr < 0) {
|
||||||
if (errno == EINTR)
|
if (errno == EINTR)
|
||||||
goto retry;
|
goto retry;
|
||||||
#ifdef EWOULDBLOCK
|
#ifdef EWOULDBLOCK
|
||||||
|
@ -222,35 +260,106 @@ retry:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif /* EWOULDBLOCK */
|
||||||
}
|
}
|
||||||
parsenleft = EOF_NLEFT;
|
nr = -1;
|
||||||
|
}
|
||||||
|
return nr;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Refill the input buffer and return the next input character:
|
||||||
|
*
|
||||||
|
* 1) If a string was pushed back on the input, pop it;
|
||||||
|
* 2) If an EOF was pushed back (parsenleft == EOF_NLEFT) or we are reading
|
||||||
|
* from a string so we can't refill the buffer, return EOF.
|
||||||
|
* 3) If there is more in this buffer, use it else call read to fill it.
|
||||||
|
* 4) Process input up to the next newline, deleting nul characters.
|
||||||
|
*/
|
||||||
|
|
||||||
|
int
|
||||||
|
preadbuffer(void)
|
||||||
|
{
|
||||||
|
char *p, *q;
|
||||||
|
int more;
|
||||||
|
int something;
|
||||||
|
char savec;
|
||||||
|
|
||||||
|
if (parsefile->strpush) {
|
||||||
|
popstring();
|
||||||
|
if (--parsenleft >= 0)
|
||||||
|
return (*parsenextc++);
|
||||||
|
}
|
||||||
|
if (parsenleft == EOF_NLEFT || parsefile->buf == NULL)
|
||||||
|
return PEOF;
|
||||||
|
flushout(&output);
|
||||||
|
flushout(&errout);
|
||||||
|
|
||||||
|
again:
|
||||||
|
if (parselleft <= 0) {
|
||||||
|
if ((parselleft = preadfd()) == -1) {
|
||||||
|
parselleft = parsenleft = EOF_NLEFT;
|
||||||
return PEOF;
|
return PEOF;
|
||||||
}
|
}
|
||||||
#if READLINE
|
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
parsenleft = i - 1;
|
q = p = parsenextc;
|
||||||
|
|
||||||
/* delete nul characters */
|
/* delete nul characters */
|
||||||
for (;;) {
|
something = 0;
|
||||||
if (*p++ == '\0')
|
for (more = 1; more;) {
|
||||||
|
switch (*p) {
|
||||||
|
case '\0':
|
||||||
|
p++; /* Skip nul */
|
||||||
|
goto check;
|
||||||
|
|
||||||
|
case '\t':
|
||||||
|
case ' ':
|
||||||
|
break;
|
||||||
|
|
||||||
|
case '\n':
|
||||||
|
parsenleft = q - parsenextc;
|
||||||
|
more = 0; /* Stop processing here */
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
something = 1;
|
||||||
break;
|
break;
|
||||||
if (--i <= 0)
|
|
||||||
return *parsenextc++; /* no nul characters */
|
|
||||||
}
|
|
||||||
q = p - 1;
|
|
||||||
while (--i > 0) {
|
|
||||||
if (*p != '\0')
|
|
||||||
*q++ = *p;
|
|
||||||
p++;
|
|
||||||
}
|
|
||||||
if (q == parsefile->buf)
|
|
||||||
goto retry; /* buffer contained nothing but nuls */
|
|
||||||
parsenleft = q - parsefile->buf - 1;
|
|
||||||
return *parsenextc++;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
*q++ = *p++;
|
||||||
|
check:
|
||||||
|
if (--parselleft <= 0) {
|
||||||
|
parsenleft = q - parsenextc - 1;
|
||||||
|
if (parsenleft < 0)
|
||||||
|
goto again;
|
||||||
|
*q = '\0';
|
||||||
|
more = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
savec = *q;
|
||||||
|
*q = '\0';
|
||||||
|
|
||||||
|
#if !defined(NO_HISTORY) && !defined(EDITLINE)
|
||||||
|
if (parsefile->fd == 0 && hist && something) {
|
||||||
|
HistEvent he;
|
||||||
|
INTOFF;
|
||||||
|
history(hist, &he, whichprompt == 1 ? H_ENTER : H_ADD,
|
||||||
|
parsenextc);
|
||||||
|
INTON;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (vflag) {
|
||||||
|
out2str(parsenextc);
|
||||||
|
flushout(out2);
|
||||||
|
}
|
||||||
|
|
||||||
|
*q = savec;
|
||||||
|
|
||||||
|
return *parsenextc++;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Undo the last call to pgetc. Only one character may be pushed back.
|
* Undo the last call to pgetc. Only one character may be pushed back.
|
||||||
|
@ -258,28 +367,57 @@ retry:
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void
|
void
|
||||||
pungetc() {
|
pungetc(void)
|
||||||
|
{
|
||||||
parsenleft++;
|
parsenleft++;
|
||||||
parsenextc--;
|
parsenextc--;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Push a string back onto the input. This code doesn't work if the user
|
* Push a string back onto the input at this current parsefile level.
|
||||||
* tries to push back more than one string at once.
|
* We handle aliases this way.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void
|
void
|
||||||
ppushback(string, length)
|
pushstring(char *s, int len, void *ap)
|
||||||
char *string;
|
|
||||||
{
|
{
|
||||||
pushedstring = parsenextc;
|
struct strpush *sp;
|
||||||
pushednleft = parsenleft;
|
|
||||||
parsenextc = string;
|
INTOFF;
|
||||||
parsenleft = length;
|
/*dprintf("*** calling pushstring: %s, %d\n", s, len);*/
|
||||||
|
if (parsefile->strpush) {
|
||||||
|
sp = ckmalloc(sizeof (struct strpush));
|
||||||
|
sp->prev = parsefile->strpush;
|
||||||
|
parsefile->strpush = sp;
|
||||||
|
} else
|
||||||
|
sp = parsefile->strpush = &(parsefile->basestrpush);
|
||||||
|
sp->prevstring = parsenextc;
|
||||||
|
sp->prevnleft = parsenleft;
|
||||||
|
sp->prevlleft = parselleft;
|
||||||
|
sp->ap = (struct alias *)ap;
|
||||||
|
if (ap)
|
||||||
|
((struct alias *)ap)->flag |= ALIASINUSE;
|
||||||
|
parsenextc = s;
|
||||||
|
parsenleft = len;
|
||||||
|
INTON;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
popstring(void)
|
||||||
|
{
|
||||||
|
struct strpush *sp = parsefile->strpush;
|
||||||
|
|
||||||
|
INTOFF;
|
||||||
|
parsenextc = sp->prevstring;
|
||||||
|
parsenleft = sp->prevnleft;
|
||||||
|
parselleft = sp->prevlleft;
|
||||||
|
/*dprintf("*** calling popstring: restoring to '%s'\n", parsenextc);*/
|
||||||
|
if (sp->ap)
|
||||||
|
sp->ap->flag &= ~ALIASINUSE;
|
||||||
|
parsefile->strpush = sp->prev;
|
||||||
|
if (sp != &(parsefile->basestrpush))
|
||||||
|
ckfree(sp);
|
||||||
|
INTON;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Set the input to take input from a file. If push is set, push the
|
* Set the input to take input from a file. If push is set, push the
|
||||||
|
@ -287,17 +425,16 @@ ppushback(string, length)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void
|
void
|
||||||
setinputfile(fname, push)
|
setinputfile(char *fname, int push)
|
||||||
char *fname;
|
|
||||||
{
|
{
|
||||||
int fd;
|
int fd;
|
||||||
int fd2;
|
int fd2;
|
||||||
|
|
||||||
INTOFF;
|
INTOFF;
|
||||||
if ((fd = open(fname, O_RDONLY)) < 0)
|
if ((fd = open(fname, O_RDONLY)) < 0)
|
||||||
error("Can't open %s", fname);
|
error("Can't open %s: %s", fname, strerror(errno));
|
||||||
if (fd < 10) {
|
if (fd < 10) {
|
||||||
fd2 = copyfd(fd, 10);
|
fd2 = fcntl(fd, F_DUPFD, 10);
|
||||||
close(fd);
|
close(fd);
|
||||||
if (fd2 < 0)
|
if (fd2 < 0)
|
||||||
error("Out of file descriptors");
|
error("Out of file descriptors");
|
||||||
|
@ -314,8 +451,9 @@ setinputfile(fname, push)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void
|
void
|
||||||
setinputfd(fd, push) {
|
setinputfd(int fd, int push)
|
||||||
(void) fcntl(fd, F_SETFD, fcntl(fd, F_GETFD) | FD_CLOEXEC);
|
{
|
||||||
|
(void)fcntl(fd, F_SETFD, FD_CLOEXEC);
|
||||||
if (push) {
|
if (push) {
|
||||||
pushfile();
|
pushfile();
|
||||||
parsefile->buf = ckmalloc(BUFSIZ);
|
parsefile->buf = ckmalloc(BUFSIZ);
|
||||||
|
@ -325,7 +463,7 @@ setinputfd(fd, push) {
|
||||||
parsefile->fd = fd;
|
parsefile->fd = fd;
|
||||||
if (parsefile->buf == NULL)
|
if (parsefile->buf == NULL)
|
||||||
parsefile->buf = ckmalloc(BUFSIZ);
|
parsefile->buf = ckmalloc(BUFSIZ);
|
||||||
parsenleft = 0;
|
parselleft = parsenleft = 0;
|
||||||
plinno = 1;
|
plinno = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -335,14 +473,13 @@ setinputfd(fd, push) {
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void
|
void
|
||||||
setinputstring(string, push)
|
setinputstring(char *string, int push)
|
||||||
char *string;
|
|
||||||
{
|
{
|
||||||
INTOFF;
|
INTOFF;
|
||||||
if (push)
|
if (push)
|
||||||
pushfile();
|
pushfile();
|
||||||
parsenextc = string;
|
parsenextc = string;
|
||||||
parsenleft = strlen(string);
|
parselleft = parsenleft = strlen(string);
|
||||||
parsefile->buf = NULL;
|
parsefile->buf = NULL;
|
||||||
plinno = 1;
|
plinno = 1;
|
||||||
INTON;
|
INTON;
|
||||||
|
@ -356,21 +493,26 @@ setinputstring(string, push)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
STATIC void
|
STATIC void
|
||||||
pushfile() {
|
pushfile(void)
|
||||||
|
{
|
||||||
struct parsefile *pf;
|
struct parsefile *pf;
|
||||||
|
|
||||||
parsefile->nleft = parsenleft;
|
parsefile->nleft = parsenleft;
|
||||||
|
parsefile->lleft = parselleft;
|
||||||
parsefile->nextc = parsenextc;
|
parsefile->nextc = parsenextc;
|
||||||
parsefile->linno = plinno;
|
parsefile->linno = plinno;
|
||||||
pf = (struct parsefile *)ckmalloc(sizeof (struct parsefile));
|
pf = (struct parsefile *)ckmalloc(sizeof (struct parsefile));
|
||||||
pf->prev = parsefile;
|
pf->prev = parsefile;
|
||||||
pf->fd = -1;
|
pf->fd = -1;
|
||||||
|
pf->strpush = NULL;
|
||||||
|
pf->basestrpush.prev = NULL;
|
||||||
parsefile = pf;
|
parsefile = pf;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
popfile() {
|
popfile(void)
|
||||||
|
{
|
||||||
struct parsefile *pf = parsefile;
|
struct parsefile *pf = parsefile;
|
||||||
|
|
||||||
INTOFF;
|
INTOFF;
|
||||||
|
@ -378,9 +520,12 @@ popfile() {
|
||||||
close(pf->fd);
|
close(pf->fd);
|
||||||
if (pf->buf)
|
if (pf->buf)
|
||||||
ckfree(pf->buf);
|
ckfree(pf->buf);
|
||||||
|
while (pf->strpush)
|
||||||
|
popstring();
|
||||||
parsefile = pf->prev;
|
parsefile = pf->prev;
|
||||||
ckfree(pf);
|
ckfree(pf);
|
||||||
parsenleft = parsefile->nleft;
|
parsenleft = parsefile->nleft;
|
||||||
|
parselleft = parsefile->lleft;
|
||||||
parsenextc = parsefile->nextc;
|
parsenextc = parsefile->nextc;
|
||||||
plinno = parsefile->linno;
|
plinno = parsefile->linno;
|
||||||
INTON;
|
INTON;
|
||||||
|
@ -392,7 +537,8 @@ popfile() {
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void
|
void
|
||||||
popallfiles() {
|
popallfiles(void)
|
||||||
|
{
|
||||||
while (parsefile != &basepf)
|
while (parsefile != &basepf)
|
||||||
popfile();
|
popfile();
|
||||||
}
|
}
|
||||||
|
@ -405,10 +551,15 @@ popallfiles() {
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void
|
void
|
||||||
closescript() {
|
closescript(void)
|
||||||
|
{
|
||||||
popallfiles();
|
popallfiles();
|
||||||
if (parsefile->fd > 0) {
|
if (parsefile->fd > 0) {
|
||||||
close(parsefile->fd);
|
close(parsefile->fd);
|
||||||
parsefile->fd = 0;
|
parsefile->fd = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* $PchId: input.c,v 1.6 2006/05/23 12:00:32 philip Exp $
|
||||||
|
*/
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/*-
|
/*-
|
||||||
* Copyright (c) 1991 The Regents of the University of California.
|
* Copyright (c) 1991, 1993
|
||||||
* All rights reserved.
|
* The Regents of the University of California. All rights reserved.
|
||||||
*
|
*
|
||||||
* This code is derived from software contributed to Berkeley by
|
* This code is derived from software contributed to Berkeley by
|
||||||
* Kenneth Almquist.
|
* Kenneth Almquist.
|
||||||
|
@ -13,10 +13,6 @@
|
||||||
* 2. Redistributions in binary form must reproduce the above copyright
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
* notice, this list of conditions and the following disclaimer in the
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
* documentation and/or other materials provided with the distribution.
|
* documentation and/or other materials provided with the distribution.
|
||||||
* 3. All advertising materials mentioning features or use of this software
|
|
||||||
* must display the following acknowledgement:
|
|
||||||
* This product includes software developed by the University of
|
|
||||||
* California, Berkeley and its contributors.
|
|
||||||
* 4. Neither the name of the University nor the names of its contributors
|
* 4. Neither the name of the University nor the names of its contributors
|
||||||
* may be used to endorse or promote products derived from this software
|
* may be used to endorse or promote products derived from this software
|
||||||
* without specific prior written permission.
|
* without specific prior written permission.
|
||||||
|
@ -33,7 +29,8 @@
|
||||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||||
* SUCH DAMAGE.
|
* SUCH DAMAGE.
|
||||||
*
|
*
|
||||||
* @(#)input.h 5.1 (Berkeley) 3/7/91
|
* @(#)input.h 8.2 (Berkeley) 5/4/95
|
||||||
|
* $FreeBSD: src/bin/sh/input.h,v 1.9 2004/04/06 20:06:51 markm Exp $
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* PEOF (the end of file marker) is defined in syntax.h */
|
/* PEOF (the end of file marker) is defined in syntax.h */
|
||||||
|
@ -46,39 +43,22 @@
|
||||||
extern int plinno;
|
extern int plinno;
|
||||||
extern int parsenleft; /* number of characters left in input buffer */
|
extern int parsenleft; /* number of characters left in input buffer */
|
||||||
extern char *parsenextc; /* next character in input buffer */
|
extern char *parsenextc; /* next character in input buffer */
|
||||||
|
extern int init_editline; /* 0 == not setup, 1 == OK, -1 == failed */
|
||||||
|
|
||||||
|
|
||||||
#ifdef __STDC__
|
|
||||||
char *pfgets(char *, int);
|
char *pfgets(char *, int);
|
||||||
int pgetc(void);
|
int pgetc(void);
|
||||||
int preadbuffer(void);
|
int preadbuffer(void);
|
||||||
void pungetc(void);
|
void pungetc(void);
|
||||||
void ppushback(char *, int);
|
void pushstring(char *, int, void *);
|
||||||
void setinputfile(char *, int);
|
void setinputfile(char *, int);
|
||||||
void setinputfd(int, int);
|
void setinputfd(int, int);
|
||||||
void setinputstring(char *, int);
|
void setinputstring(char *, int);
|
||||||
void popfile(void);
|
void popfile(void);
|
||||||
void popallfiles(void);
|
void popallfiles(void);
|
||||||
void closescript(void);
|
void closescript(void);
|
||||||
#else
|
|
||||||
char *pfgets();
|
|
||||||
int pgetc();
|
|
||||||
int preadbuffer();
|
|
||||||
void pungetc();
|
|
||||||
void ppushback();
|
|
||||||
void setinputfile();
|
|
||||||
void setinputfd();
|
|
||||||
void setinputstring();
|
|
||||||
void popfile();
|
|
||||||
void popallfiles();
|
|
||||||
void closescript();
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define pgetc_macro() (--parsenleft >= 0? *parsenextc++ : preadbuffer())
|
#define pgetc_macro() (--parsenleft >= 0? *parsenextc++ : preadbuffer())
|
||||||
|
|
||||||
#if READLINE
|
/*
|
||||||
/* The variable "r_use_prompt" indicates the prompt to use with readline,
|
* $PchId: input.h,v 1.3 2006/03/30 13:49:37 philip Exp $
|
||||||
* *and* that readline may only be used if non-NULL.
|
|
||||||
*/
|
*/
|
||||||
extern char *r_use_prompt;
|
|
||||||
#endif
|
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -1,6 +1,6 @@
|
||||||
/*-
|
/*-
|
||||||
* Copyright (c) 1991 The Regents of the University of California.
|
* Copyright (c) 1991, 1993
|
||||||
* All rights reserved.
|
* The Regents of the University of California. All rights reserved.
|
||||||
*
|
*
|
||||||
* This code is derived from software contributed to Berkeley by
|
* This code is derived from software contributed to Berkeley by
|
||||||
* Kenneth Almquist.
|
* Kenneth Almquist.
|
||||||
|
@ -13,10 +13,6 @@
|
||||||
* 2. Redistributions in binary form must reproduce the above copyright
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
* notice, this list of conditions and the following disclaimer in the
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
* documentation and/or other materials provided with the distribution.
|
* documentation and/or other materials provided with the distribution.
|
||||||
* 3. All advertising materials mentioning features or use of this software
|
|
||||||
* must display the following acknowledgement:
|
|
||||||
* This product includes software developed by the University of
|
|
||||||
* California, Berkeley and its contributors.
|
|
||||||
* 4. Neither the name of the University nor the names of its contributors
|
* 4. Neither the name of the University nor the names of its contributors
|
||||||
* may be used to endorse or promote products derived from this software
|
* may be used to endorse or promote products derived from this software
|
||||||
* without specific prior written permission.
|
* without specific prior written permission.
|
||||||
|
@ -33,7 +29,8 @@
|
||||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||||
* SUCH DAMAGE.
|
* SUCH DAMAGE.
|
||||||
*
|
*
|
||||||
* @(#)jobs.h 5.1 (Berkeley) 3/7/91
|
* @(#)jobs.h 8.2 (Berkeley) 5/4/95
|
||||||
|
* $FreeBSD: src/bin/sh/jobs.h,v 1.18 2004/04/06 20:06:51 markm Exp $
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* Mode argument to forkshell. Don't change FORK_FG or FORK_BG. */
|
/* Mode argument to forkshell. Don't change FORK_FG or FORK_BG. */
|
||||||
|
@ -41,6 +38,7 @@
|
||||||
#define FORK_BG 1
|
#define FORK_BG 1
|
||||||
#define FORK_NOJOB 2
|
#define FORK_NOJOB 2
|
||||||
|
|
||||||
|
#include <signal.h> /* for sig_atomic_t */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* A job structure contains information about a job. A job is either a
|
* A job structure contains information about a job. A job is either a
|
||||||
|
@ -51,7 +49,7 @@
|
||||||
|
|
||||||
struct procstat {
|
struct procstat {
|
||||||
pid_t pid; /* process id */
|
pid_t pid; /* process id */
|
||||||
short status; /* status flags (defined above) */
|
int status; /* status flags (defined above) */
|
||||||
char *cmd; /* text of command being run */
|
char *cmd; /* text of command being run */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -64,33 +62,41 @@ struct procstat {
|
||||||
struct job {
|
struct job {
|
||||||
struct procstat ps0; /* status of process */
|
struct procstat ps0; /* status of process */
|
||||||
struct procstat *ps; /* status or processes when more than one */
|
struct procstat *ps; /* status or processes when more than one */
|
||||||
pid_t nprocs; /* number of processes */
|
short nprocs; /* number of processes */
|
||||||
pid_t pgrp; /* process group of this job */
|
pid_t pgrp; /* process group of this job */
|
||||||
char state; /* true if job is finished */
|
char state; /* true if job is finished */
|
||||||
char used; /* true if this entry is in used */
|
char used; /* true if this entry is in used */
|
||||||
char changed; /* true if status has changed */
|
char changed; /* true if status has changed */
|
||||||
|
char foreground; /* true if running in the foreground */
|
||||||
#if JOBS
|
#if JOBS
|
||||||
char jobctl; /* job running under job control */
|
char jobctl; /* job running under job control */
|
||||||
|
struct job *next; /* job used after this one */
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
extern pid_t backgndpid; /* pid of last background process */
|
extern pid_t backgndpid; /* pid of last background process */
|
||||||
|
extern int job_warning; /* user was warned about stopped jobs */
|
||||||
|
extern int in_waitcmd; /* are we in waitcmd()? */
|
||||||
|
extern int in_dowait; /* are we in dowait()? */
|
||||||
|
extern volatile sig_atomic_t breakwaitcmd; /* break wait to process traps? */
|
||||||
|
|
||||||
|
|
||||||
#ifdef __STDC__
|
|
||||||
void setjobctl(int);
|
void setjobctl(int);
|
||||||
void showjobs(int);
|
int fgcmd(int, char **);
|
||||||
|
int bgcmd(int, char **);
|
||||||
|
int jobscmd(int, char **);
|
||||||
|
void showjobs(int, int, int);
|
||||||
|
int waitcmd(int, char **);
|
||||||
|
int jobidcmd(int, char **);
|
||||||
struct job *makejob(union node *, int);
|
struct job *makejob(union node *, int);
|
||||||
int forkshell(struct job *, union node *, int);
|
pid_t forkshell(struct job *, union node *, int);
|
||||||
int waitforjob(struct job *);
|
int waitforjob(struct job *, int *);
|
||||||
#else
|
int stoppedjobs(void);
|
||||||
void setjobctl();
|
char *commandtext(union node *);
|
||||||
void showjobs();
|
|
||||||
struct job *makejob();
|
|
||||||
int forkshell();
|
|
||||||
int waitforjob();
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if ! JOBS
|
#if ! JOBS
|
||||||
#define setjobctl(on) /* do nothing */
|
#define setjobctl(on) /* do nothing */
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
* $PchId: jobs.h,v 1.4 2006/03/30 12:07:24 philip Exp $
|
||||||
|
*/
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/*-
|
/*-
|
||||||
* Copyright (c) 1991 The Regents of the University of California.
|
* Copyright (c) 1991, 1993
|
||||||
* All rights reserved.
|
* The Regents of the University of California. All rights reserved.
|
||||||
*
|
*
|
||||||
* This code is derived from software contributed to Berkeley by
|
* This code is derived from software contributed to Berkeley by
|
||||||
* Kenneth Almquist.
|
* Kenneth Almquist.
|
||||||
|
@ -33,7 +33,7 @@
|
||||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||||
* SUCH DAMAGE.
|
* SUCH DAMAGE.
|
||||||
*
|
*
|
||||||
* @(#)machdep.h 5.1 (Berkeley) 3/7/91
|
* @(#)machdep.h 8.2 (Berkeley) 5/4/95
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -47,5 +47,9 @@ union align {
|
||||||
char *cp;
|
char *cp;
|
||||||
};
|
};
|
||||||
|
|
||||||
#define ALIGN(nbytes) ((nbytes) + sizeof(union align) - 1 &~ (sizeof(union align) - 1))
|
#define ALIGN(nbytes) (((nbytes) + sizeof(union align) - 1) & ~(sizeof(union align) - 1))
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
* $PchId: machdep.h,v 1.2 2001/05/15 16:36:26 philip Exp $
|
||||||
|
*/
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/*-
|
/*-
|
||||||
* Copyright (c) 1991 The Regents of the University of California.
|
* Copyright (c) 1991, 1993
|
||||||
* All rights reserved.
|
* The Regents of the University of California. All rights reserved.
|
||||||
*
|
*
|
||||||
* This code is derived from software contributed to Berkeley by
|
* This code is derived from software contributed to Berkeley by
|
||||||
* Kenneth Almquist.
|
* Kenneth Almquist.
|
||||||
|
@ -13,10 +13,6 @@
|
||||||
* 2. Redistributions in binary form must reproduce the above copyright
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
* notice, this list of conditions and the following disclaimer in the
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
* documentation and/or other materials provided with the distribution.
|
* documentation and/or other materials provided with the distribution.
|
||||||
* 3. All advertising materials mentioning features or use of this software
|
|
||||||
* must display the following acknowledgement:
|
|
||||||
* This product includes software developed by the University of
|
|
||||||
* California, Berkeley and its contributors.
|
|
||||||
* 4. Neither the name of the University nor the names of its contributors
|
* 4. Neither the name of the University nor the names of its contributors
|
||||||
* may be used to endorse or promote products derived from this software
|
* may be used to endorse or promote products derived from this software
|
||||||
* without specific prior written permission.
|
* without specific prior written permission.
|
||||||
|
@ -35,8 +31,14 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef lint
|
#ifndef lint
|
||||||
static char sccsid[] = "@(#)mail.c 5.1 (Berkeley) 3/7/91";
|
#if 0
|
||||||
|
static char sccsid[] = "@(#)mail.c 8.2 (Berkeley) 5/4/95";
|
||||||
|
#endif
|
||||||
#endif /* not lint */
|
#endif /* not lint */
|
||||||
|
/*
|
||||||
|
#include <sys/cdefs.h>
|
||||||
|
__FBSDID("$FreeBSD: src/bin/sh/mail.c,v 1.13 2004/04/06 20:06:51 markm Exp $");
|
||||||
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Routines to check for mail. (Perhaps make part of main.c?)
|
* Routines to check for mail. (Perhaps make part of main.c?)
|
||||||
|
@ -48,8 +50,10 @@ static char sccsid[] = "@(#)mail.c 5.1 (Berkeley) 3/7/91";
|
||||||
#include "output.h"
|
#include "output.h"
|
||||||
#include "memalloc.h"
|
#include "memalloc.h"
|
||||||
#include "error.h"
|
#include "error.h"
|
||||||
|
#include "mail.h"
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
|
||||||
#define MAXMBOXES 10
|
#define MAXMBOXES 10
|
||||||
|
@ -67,11 +71,12 @@ STATIC time_t mailtime[MAXMBOXES]; /* times of mailboxes */
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void
|
void
|
||||||
chkmail(silent) {
|
chkmail(int silent)
|
||||||
register int i;
|
{
|
||||||
|
int i;
|
||||||
char *mpath;
|
char *mpath;
|
||||||
char *p;
|
char *p;
|
||||||
register char *q;
|
char *q;
|
||||||
struct stackmark smark;
|
struct stackmark smark;
|
||||||
struct stat statb;
|
struct stat statb;
|
||||||
|
|
||||||
|
@ -91,18 +96,28 @@ chkmail(silent) {
|
||||||
if (q[-1] != '/')
|
if (q[-1] != '/')
|
||||||
abort();
|
abort();
|
||||||
q[-1] = '\0'; /* delete trailing '/' */
|
q[-1] = '\0'; /* delete trailing '/' */
|
||||||
|
#ifdef notdef /* this is what the System V shell claims to do (it lies) */
|
||||||
if (stat(p, &statb) < 0)
|
if (stat(p, &statb) < 0)
|
||||||
statb.st_mtime = 0;
|
statb.st_mtime = 0;
|
||||||
if (!silent
|
if (statb.st_mtime > mailtime[i] && ! silent) {
|
||||||
&& statb.st_size > 0
|
out2str(pathopt? pathopt : "you have mail");
|
||||||
&& statb.st_mtime > mailtime[i]
|
|
||||||
&& statb.st_mtime > statb.st_atime
|
|
||||||
) {
|
|
||||||
out2str(pathopt? pathopt : "You have mail");
|
|
||||||
out2c('\n');
|
out2c('\n');
|
||||||
}
|
}
|
||||||
mailtime[i] = statb.st_mtime;
|
mailtime[i] = statb.st_mtime;
|
||||||
|
#else /* this is what it should do */
|
||||||
|
if (stat(p, &statb) < 0)
|
||||||
|
statb.st_size = 0;
|
||||||
|
if (statb.st_size > mailtime[i] && ! silent) {
|
||||||
|
out2str(pathopt? pathopt : "you have mail");
|
||||||
|
out2c('\n');
|
||||||
|
}
|
||||||
|
mailtime[i] = statb.st_size;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
nmboxes = i;
|
nmboxes = i;
|
||||||
popstackmark(&smark);
|
popstackmark(&smark);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* $PchId: mail.c,v 1.5 2006/05/22 12:02:37 philip Exp $
|
||||||
|
*/
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/*-
|
/*-
|
||||||
* Copyright (c) 1991 The Regents of the University of California.
|
* Copyright (c) 1991, 1993
|
||||||
* All rights reserved.
|
* The Regents of the University of California. All rights reserved.
|
||||||
*
|
*
|
||||||
* This code is derived from software contributed to Berkeley by
|
* This code is derived from software contributed to Berkeley by
|
||||||
* Kenneth Almquist.
|
* Kenneth Almquist.
|
||||||
|
@ -13,10 +13,6 @@
|
||||||
* 2. Redistributions in binary form must reproduce the above copyright
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
* notice, this list of conditions and the following disclaimer in the
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
* documentation and/or other materials provided with the distribution.
|
* documentation and/or other materials provided with the distribution.
|
||||||
* 3. All advertising materials mentioning features or use of this software
|
|
||||||
* must display the following acknowledgement:
|
|
||||||
* This product includes software developed by the University of
|
|
||||||
* California, Berkeley and its contributors.
|
|
||||||
* 4. Neither the name of the University nor the names of its contributors
|
* 4. Neither the name of the University nor the names of its contributors
|
||||||
* may be used to endorse or promote products derived from this software
|
* may be used to endorse or promote products derived from this software
|
||||||
* without specific prior written permission.
|
* without specific prior written permission.
|
||||||
|
@ -33,11 +29,12 @@
|
||||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||||
* SUCH DAMAGE.
|
* SUCH DAMAGE.
|
||||||
*
|
*
|
||||||
* @(#)mail.h 5.1 (Berkeley) 3/7/91
|
* @(#)mail.h 8.2 (Berkeley) 5/4/95
|
||||||
|
* $FreeBSD: src/bin/sh/mail.h,v 1.8 2004/04/06 20:06:51 markm Exp $
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifdef __STDC__
|
|
||||||
void chkmail(int);
|
void chkmail(int);
|
||||||
#else
|
|
||||||
void chkmail();
|
/*
|
||||||
#endif
|
* $PchId: mail.h,v 1.3 2006/03/30 11:53:44 philip Exp $
|
||||||
|
*/
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/*-
|
/*-
|
||||||
* Copyright (c) 1991 The Regents of the University of California.
|
* Copyright (c) 1991, 1993
|
||||||
* All rights reserved.
|
* The Regents of the University of California. All rights reserved.
|
||||||
*
|
*
|
||||||
* This code is derived from software contributed to Berkeley by
|
* This code is derived from software contributed to Berkeley by
|
||||||
* Kenneth Almquist.
|
* Kenneth Almquist.
|
||||||
|
@ -13,10 +13,6 @@
|
||||||
* 2. Redistributions in binary form must reproduce the above copyright
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
* notice, this list of conditions and the following disclaimer in the
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
* documentation and/or other materials provided with the distribution.
|
* documentation and/or other materials provided with the distribution.
|
||||||
* 3. All advertising materials mentioning features or use of this software
|
|
||||||
* must display the following acknowledgement:
|
|
||||||
* This product includes software developed by the University of
|
|
||||||
* California, Berkeley and its contributors.
|
|
||||||
* 4. Neither the name of the University nor the names of its contributors
|
* 4. Neither the name of the University nor the names of its contributors
|
||||||
* may be used to endorse or promote products derived from this software
|
* may be used to endorse or promote products derived from this software
|
||||||
* without specific prior written permission.
|
* without specific prior written permission.
|
||||||
|
@ -35,18 +31,29 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef lint
|
#ifndef lint
|
||||||
char copyright[] =
|
static char const copyright[] =
|
||||||
"@(#) Copyright (c) 1991 The Regents of the University of California.\n\
|
"@(#) Copyright (c) 1991, 1993\n\
|
||||||
All rights reserved.\n";
|
The Regents of the University of California. All rights reserved.\n";
|
||||||
#endif /* not lint */
|
#endif /* not lint */
|
||||||
|
|
||||||
#ifndef lint
|
#ifndef lint
|
||||||
static char sccsid[] = "@(#)main.c 5.2 (Berkeley) 3/13/91";
|
#if 0
|
||||||
|
static char sccsid[] = "@(#)main.c 8.6 (Berkeley) 5/28/95";
|
||||||
|
#endif
|
||||||
#endif /* not lint */
|
#endif /* not lint */
|
||||||
|
/*
|
||||||
|
#include <sys/cdefs.h>
|
||||||
|
__FBSDID("$FreeBSD: src/bin/sh/main.c,v 1.26 2004/04/06 20:06:51 markm Exp $");
|
||||||
|
*/
|
||||||
|
|
||||||
#include <sys/types.h>
|
#include <stdio.h>
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <unistd.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
|
#include <locale.h>
|
||||||
|
#include <errno.h>
|
||||||
|
|
||||||
#include "shell.h"
|
#include "shell.h"
|
||||||
#include "main.h"
|
#include "main.h"
|
||||||
#include "mail.h"
|
#include "mail.h"
|
||||||
|
@ -54,38 +61,26 @@ static char sccsid[] = "@(#)main.c 5.2 (Berkeley) 3/13/91";
|
||||||
#include "output.h"
|
#include "output.h"
|
||||||
#include "parser.h"
|
#include "parser.h"
|
||||||
#include "nodes.h"
|
#include "nodes.h"
|
||||||
|
#include "expand.h"
|
||||||
#include "eval.h"
|
#include "eval.h"
|
||||||
#include "jobs.h"
|
#include "jobs.h"
|
||||||
#include "input.h"
|
#include "input.h"
|
||||||
#include "trap.h"
|
#include "trap.h"
|
||||||
#if ATTY
|
|
||||||
#include "var.h"
|
#include "var.h"
|
||||||
#endif
|
#include "show.h"
|
||||||
#include "memalloc.h"
|
#include "memalloc.h"
|
||||||
#include "error.h"
|
#include "error.h"
|
||||||
#include "init.h"
|
#include "init.h"
|
||||||
#include "mystring.h"
|
#include "mystring.h"
|
||||||
|
#include "exec.h"
|
||||||
#define PROFILE 0
|
#include "cd.h"
|
||||||
|
#include "builtins.h"
|
||||||
|
|
||||||
int rootpid;
|
int rootpid;
|
||||||
int rootshell;
|
int rootshell;
|
||||||
STATIC union node *curcmd;
|
|
||||||
STATIC union node *prevcmd;
|
|
||||||
extern int errno;
|
|
||||||
#if PROFILE
|
|
||||||
short profile_buf[16384];
|
|
||||||
extern int etext();
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef __STDC__
|
|
||||||
STATIC void read_profile(char *);
|
STATIC void read_profile(char *);
|
||||||
char *getenv(char *);
|
STATIC char *find_dot_file(char *);
|
||||||
#else
|
|
||||||
STATIC void read_profile();
|
|
||||||
char *getenv();
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Main routine. We initialize things, parse the arguments, execute
|
* Main routine. We initialize things, parse the arguments, execute
|
||||||
|
@ -95,16 +90,15 @@ char *getenv();
|
||||||
* is used to figure out how far we had gotten.
|
* is used to figure out how far we had gotten.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
main(argc, argv) char **argv; {
|
int
|
||||||
|
main(int argc, char *argv[])
|
||||||
|
{
|
||||||
struct jmploc jmploc;
|
struct jmploc jmploc;
|
||||||
struct stackmark smark;
|
struct stackmark smark;
|
||||||
volatile int state;
|
volatile int state;
|
||||||
char *shinit, *home;
|
char *shinit;
|
||||||
char *profile = NULL, *ashrc = NULL;
|
|
||||||
|
|
||||||
#if PROFILE
|
(void) setlocale(LC_ALL, "");
|
||||||
monitor(4, etext, profile_buf, sizeof profile_buf, 50);
|
|
||||||
#endif
|
|
||||||
state = 0;
|
state = 0;
|
||||||
if (setjmp(jmploc.loc)) {
|
if (setjmp(jmploc.loc)) {
|
||||||
/*
|
/*
|
||||||
|
@ -112,21 +106,32 @@ main(argc, argv) char **argv; {
|
||||||
* exception EXSHELLPROC to clean up before executing
|
* exception EXSHELLPROC to clean up before executing
|
||||||
* the shell procedure.
|
* the shell procedure.
|
||||||
*/
|
*/
|
||||||
if (exception == EXSHELLPROC) {
|
switch (exception) {
|
||||||
|
case EXSHELLPROC:
|
||||||
rootpid = getpid();
|
rootpid = getpid();
|
||||||
rootshell = 1;
|
rootshell = 1;
|
||||||
minusc = NULL;
|
minusc = NULL;
|
||||||
state = 3;
|
state = 3;
|
||||||
} else if (state == 0 || iflag == 0 || ! rootshell)
|
break;
|
||||||
exitshell(2);
|
|
||||||
|
case EXEXEC:
|
||||||
|
exitstatus = exerrno;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case EXERROR:
|
||||||
|
exitstatus = 2;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (exception != EXSHELLPROC) {
|
||||||
|
if (state == 0 || iflag == 0 || ! rootshell)
|
||||||
|
exitshell(exitstatus);
|
||||||
|
}
|
||||||
reset();
|
reset();
|
||||||
#if ATTY
|
if (exception == EXINT) {
|
||||||
if (exception == EXINT
|
|
||||||
&& (! attyset() || equal(termval(), "emacs")))
|
|
||||||
#else
|
|
||||||
if (exception == EXINT)
|
|
||||||
#endif
|
|
||||||
{
|
|
||||||
out2c('\n');
|
out2c('\n');
|
||||||
flushout(&errout);
|
flushout(&errout);
|
||||||
}
|
}
|
||||||
|
@ -151,57 +156,38 @@ main(argc, argv) char **argv; {
|
||||||
init();
|
init();
|
||||||
setstackmark(&smark);
|
setstackmark(&smark);
|
||||||
procargs(argc, argv);
|
procargs(argc, argv);
|
||||||
if (eflag) eflag = 2; /* Truly enable [ex]flag after init. */
|
if (getpwd() == NULL && iflag)
|
||||||
if (xflag) xflag = 2;
|
out2str("sh: cannot determine working directory\n");
|
||||||
if (argv[0] && argv[0][0] == '-') {
|
if (argv[0] && argv[0][0] == '-') {
|
||||||
state = 1;
|
state = 1;
|
||||||
read_profile("/etc/profile");
|
read_profile("/etc/profile");
|
||||||
state1:
|
state1:
|
||||||
state = 2;
|
state = 2;
|
||||||
if ((home = getenv("HOME")) != NULL
|
if (privileged == 0)
|
||||||
&& (profile = (char *) malloc(strlen(home) + 10)) != NULL)
|
|
||||||
{
|
|
||||||
strcpy(profile, home);
|
|
||||||
strcat(profile, "/.profile");
|
|
||||||
read_profile(profile);
|
|
||||||
} else {
|
|
||||||
read_profile(".profile");
|
read_profile(".profile");
|
||||||
}
|
else
|
||||||
} else if ((sflag || minusc) && (shinit = getenv("SHINIT")) != NULL) {
|
read_profile("/etc/suid_profile");
|
||||||
state = 2;
|
|
||||||
evalstring(shinit);
|
|
||||||
}
|
}
|
||||||
state2:
|
state2:
|
||||||
if (profile != NULL) free(profile);
|
|
||||||
|
|
||||||
state = 3;
|
state = 3;
|
||||||
if (!argv[0] || argv[0][0] != '-') {
|
if (!privileged && iflag) {
|
||||||
if ((home = getenv("HOME")) != NULL
|
if ((shinit = lookupvar("ENV")) != NULL && *shinit != '\0') {
|
||||||
&& (ashrc = (char *) malloc(strlen(home) + 8)) != NULL)
|
state = 3;
|
||||||
{
|
read_profile(shinit);
|
||||||
strcpy(ashrc, home);
|
|
||||||
strcat(ashrc, "/.ashrc");
|
|
||||||
read_profile(ashrc);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
state3:
|
state3:
|
||||||
if (ashrc != NULL) free(ashrc);
|
|
||||||
if (eflag) eflag = 1; /* Init done, enable [ex]flag */
|
|
||||||
if (xflag) xflag = 1;
|
|
||||||
exitstatus = 0; /* Init shouldn't influence initial $? */
|
|
||||||
|
|
||||||
state = 4;
|
state = 4;
|
||||||
if (minusc) {
|
if (minusc) {
|
||||||
evalstring(minusc);
|
evalstring(minusc);
|
||||||
}
|
}
|
||||||
if (sflag || minusc == NULL) {
|
if (sflag || minusc == NULL) {
|
||||||
state4:
|
state4: /* XXX ??? - why isn't this before the "if" statement */
|
||||||
cmdloop(1);
|
cmdloop(1);
|
||||||
}
|
}
|
||||||
#if PROFILE
|
|
||||||
monitor(0);
|
|
||||||
#endif
|
|
||||||
exitshell(exitstatus);
|
exitshell(exitstatus);
|
||||||
|
/*NOTREACHED*/
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -211,52 +197,49 @@ state4:
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void
|
void
|
||||||
cmdloop(top) {
|
cmdloop(int top)
|
||||||
|
{
|
||||||
union node *n;
|
union node *n;
|
||||||
struct stackmark smark;
|
struct stackmark smark;
|
||||||
int inter;
|
int inter;
|
||||||
int numeof;
|
int numeof = 0;
|
||||||
|
|
||||||
TRACE(("cmdloop(%d) called\n", top));
|
TRACE(("cmdloop(%d) called\n", top));
|
||||||
setstackmark(&smark);
|
setstackmark(&smark);
|
||||||
numeof = 0;
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
if (pendingsigs)
|
if (pendingsigs)
|
||||||
dotrap();
|
dotrap();
|
||||||
inter = 0;
|
inter = 0;
|
||||||
if (iflag && top) {
|
if (iflag && top) {
|
||||||
inter++;
|
inter++;
|
||||||
showjobs(1);
|
showjobs(1, 0, 0);
|
||||||
chkmail(0);
|
chkmail(0);
|
||||||
flushout(&output);
|
flushout(&output);
|
||||||
}
|
}
|
||||||
n = parsecmd(inter);
|
n = parsecmd(inter);
|
||||||
#if DEBUG
|
/* showtree(n); DEBUG */
|
||||||
/* showtree(n); */
|
|
||||||
#endif
|
|
||||||
if (n == NEOF) {
|
if (n == NEOF) {
|
||||||
if (Iflag == 0 || numeof >= 50)
|
if (!top || numeof >= 50)
|
||||||
|
break;
|
||||||
|
if (!stoppedjobs()) {
|
||||||
|
if (!Iflag)
|
||||||
break;
|
break;
|
||||||
out2str("\nUse \"exit\" to leave shell.\n");
|
out2str("\nUse \"exit\" to leave shell.\n");
|
||||||
|
}
|
||||||
numeof++;
|
numeof++;
|
||||||
} else if (n != NULL && nflag == 0) {
|
} else if (n != NULL && nflag == 0) {
|
||||||
if (inter) {
|
job_warning = (job_warning == 2) ? 1 : 0;
|
||||||
INTOFF;
|
numeof = 0;
|
||||||
if (prevcmd)
|
|
||||||
freefunc(prevcmd);
|
|
||||||
prevcmd = curcmd;
|
|
||||||
curcmd = copyfunc(n);
|
|
||||||
INTON;
|
|
||||||
}
|
|
||||||
evaltree(n, 0);
|
evaltree(n, 0);
|
||||||
#ifdef notdef
|
|
||||||
if (exitstatus) /*DEBUG*/
|
|
||||||
outfmt(&errout, "Exit status 0x%X\n", exitstatus);
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
popstackmark(&smark);
|
popstackmark(&smark);
|
||||||
|
setstackmark(&smark);
|
||||||
|
if (evalskip == SKIPFILE) {
|
||||||
|
evalskip = 0;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
popstackmark(&smark); /* unnecessary */
|
}
|
||||||
|
popstackmark(&smark);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -266,8 +249,7 @@ cmdloop(top) {
|
||||||
*/
|
*/
|
||||||
|
|
||||||
STATIC void
|
STATIC void
|
||||||
read_profile(name)
|
read_profile(char *name)
|
||||||
char *name;
|
|
||||||
{
|
{
|
||||||
int fd;
|
int fd;
|
||||||
|
|
||||||
|
@ -288,8 +270,7 @@ read_profile(name)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void
|
void
|
||||||
readcmdfile(name)
|
readcmdfile(char *name)
|
||||||
char *name;
|
|
||||||
{
|
{
|
||||||
int fd;
|
int fd;
|
||||||
|
|
||||||
|
@ -297,23 +278,55 @@ readcmdfile(name)
|
||||||
if ((fd = open(name, O_RDONLY)) >= 0)
|
if ((fd = open(name, O_RDONLY)) >= 0)
|
||||||
setinputfd(fd, 1);
|
setinputfd(fd, 1);
|
||||||
else
|
else
|
||||||
error("Can't open %s", name);
|
error("Can't open %s: %s", name, strerror(errno));
|
||||||
INTON;
|
INTON;
|
||||||
cmdloop(0);
|
cmdloop(0);
|
||||||
popfile();
|
popfile();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Take commands from a file. To be compatable we should do a path
|
* Take commands from a file. To be compatible we should do a path
|
||||||
* search for the file, but a path search doesn't make any sense.
|
* search for the file, which is necessary to find sub-commands.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
dotcmd(argc, argv) char **argv; {
|
|
||||||
|
STATIC char *
|
||||||
|
find_dot_file(char *basename)
|
||||||
|
{
|
||||||
|
static char localname[FILENAME_MAX+1];
|
||||||
|
char *fullname;
|
||||||
|
char *path = pathval();
|
||||||
|
struct stat statb;
|
||||||
|
|
||||||
|
/* don't try this for absolute or relative paths */
|
||||||
|
if( strchr(basename, '/'))
|
||||||
|
return basename;
|
||||||
|
|
||||||
|
while ((fullname = padvance(&path, basename)) != NULL) {
|
||||||
|
strcpy(localname, fullname);
|
||||||
|
stunalloc(fullname);
|
||||||
|
if ((stat(fullname, &statb) == 0) && S_ISREG(statb.st_mode))
|
||||||
|
return localname;
|
||||||
|
}
|
||||||
|
return basename;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
dotcmd(int argc, char **argv)
|
||||||
|
{
|
||||||
|
struct strlist *sp;
|
||||||
exitstatus = 0;
|
exitstatus = 0;
|
||||||
|
|
||||||
|
for (sp = cmdenviron; sp ; sp = sp->next)
|
||||||
|
setvareq(savestr(sp->text), VSTRFIXED|VTEXTFIXED);
|
||||||
|
|
||||||
if (argc >= 2) { /* That's what SVR2 does */
|
if (argc >= 2) { /* That's what SVR2 does */
|
||||||
setinputfile(argv[1], 1);
|
char *fullname = find_dot_file(argv[1]);
|
||||||
commandname = argv[1];
|
|
||||||
|
setinputfile(fullname, 1);
|
||||||
|
commandname = fullname;
|
||||||
cmdloop(0);
|
cmdloop(0);
|
||||||
popfile();
|
popfile();
|
||||||
}
|
}
|
||||||
|
@ -321,40 +334,22 @@ dotcmd(argc, argv) char **argv; {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
exitcmd(argc, argv) char **argv; {
|
int
|
||||||
|
exitcmd(int argc, char **argv)
|
||||||
|
{
|
||||||
extern int oexitstatus;
|
extern int oexitstatus;
|
||||||
|
|
||||||
|
if (stoppedjobs())
|
||||||
|
return 0;
|
||||||
if (argc > 1)
|
if (argc > 1)
|
||||||
exitstatus = number(argv[1]);
|
exitstatus = number(argv[1]);
|
||||||
else
|
else
|
||||||
exitstatus = oexitstatus;
|
exitstatus = oexitstatus;
|
||||||
exitshell(exitstatus);
|
exitshell(exitstatus);
|
||||||
}
|
/*NOTREACHED*/
|
||||||
|
|
||||||
|
|
||||||
lccmd(argc, argv) char **argv; {
|
|
||||||
if (argc > 1) {
|
|
||||||
defun(argv[1], prevcmd);
|
|
||||||
return 0;
|
return 0;
|
||||||
} else {
|
|
||||||
INTOFF;
|
|
||||||
freefunc(curcmd);
|
|
||||||
curcmd = prevcmd;
|
|
||||||
prevcmd = NULL;
|
|
||||||
INTON;
|
|
||||||
evaltree(curcmd, 0);
|
|
||||||
return exitstatus;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef notdef
|
|
||||||
/*
|
/*
|
||||||
* Should never be called.
|
* $PchId: main.c,v 1.5 2006/05/22 12:03:02 philip Exp $
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void
|
|
||||||
exit(exitstatus) {
|
|
||||||
_exit(exitstatus);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/*-
|
/*-
|
||||||
* Copyright (c) 1991 The Regents of the University of California.
|
* Copyright (c) 1991, 1993
|
||||||
* All rights reserved.
|
* The Regents of the University of California. All rights reserved.
|
||||||
*
|
*
|
||||||
* This code is derived from software contributed to Berkeley by
|
* This code is derived from software contributed to Berkeley by
|
||||||
* Kenneth Almquist.
|
* Kenneth Almquist.
|
||||||
|
@ -13,10 +13,6 @@
|
||||||
* 2. Redistributions in binary form must reproduce the above copyright
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
* notice, this list of conditions and the following disclaimer in the
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
* documentation and/or other materials provided with the distribution.
|
* documentation and/or other materials provided with the distribution.
|
||||||
* 3. All advertising materials mentioning features or use of this software
|
|
||||||
* must display the following acknowledgement:
|
|
||||||
* This product includes software developed by the University of
|
|
||||||
* California, Berkeley and its contributors.
|
|
||||||
* 4. Neither the name of the University nor the names of its contributors
|
* 4. Neither the name of the University nor the names of its contributors
|
||||||
* may be used to endorse or promote products derived from this software
|
* may be used to endorse or promote products derived from this software
|
||||||
* without specific prior written permission.
|
* without specific prior written permission.
|
||||||
|
@ -33,16 +29,18 @@
|
||||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||||
* SUCH DAMAGE.
|
* SUCH DAMAGE.
|
||||||
*
|
*
|
||||||
* @(#)main.h 5.1 (Berkeley) 3/7/91
|
* @(#)main.h 8.2 (Berkeley) 5/4/95
|
||||||
|
* $FreeBSD: src/bin/sh/main.h,v 1.8 2004/04/06 20:06:51 markm Exp $
|
||||||
*/
|
*/
|
||||||
|
|
||||||
extern int rootpid; /* pid of main shell */
|
extern int rootpid; /* pid of main shell */
|
||||||
extern int rootshell; /* true if we aren't a child of the main shell */
|
extern int rootshell; /* true if we aren't a child of the main shell */
|
||||||
|
|
||||||
#ifdef __STDC__
|
|
||||||
void readcmdfile(char *);
|
void readcmdfile(char *);
|
||||||
void cmdloop(int);
|
void cmdloop(int);
|
||||||
#else
|
int dotcmd(int, char **);
|
||||||
void readcmdfile();
|
int exitcmd(int, char **);
|
||||||
void cmdloop();
|
|
||||||
#endif
|
/*
|
||||||
|
* $PchId: main.h,v 1.3 2006/03/30 11:43:59 philip Exp $
|
||||||
|
*/
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/*-
|
/*-
|
||||||
* Copyright (c) 1991 The Regents of the University of California.
|
* Copyright (c) 1991, 1993
|
||||||
* All rights reserved.
|
* The Regents of the University of California. All rights reserved.
|
||||||
*
|
*
|
||||||
* This code is derived from software contributed to Berkeley by
|
* This code is derived from software contributed to Berkeley by
|
||||||
* Kenneth Almquist.
|
* Kenneth Almquist.
|
||||||
|
@ -13,10 +13,6 @@
|
||||||
* 2. Redistributions in binary form must reproduce the above copyright
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
* notice, this list of conditions and the following disclaimer in the
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
* documentation and/or other materials provided with the distribution.
|
* documentation and/or other materials provided with the distribution.
|
||||||
* 3. All advertising materials mentioning features or use of this software
|
|
||||||
* must display the following acknowledgement:
|
|
||||||
* This product includes software developed by the University of
|
|
||||||
* California, Berkeley and its contributors.
|
|
||||||
* 4. Neither the name of the University nor the names of its contributors
|
* 4. Neither the name of the University nor the names of its contributors
|
||||||
* may be used to endorse or promote products derived from this software
|
* may be used to endorse or promote products derived from this software
|
||||||
* without specific prior written permission.
|
* without specific prior written permission.
|
||||||
|
@ -35,24 +31,33 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef lint
|
#ifndef lint
|
||||||
static char sccsid[] = "@(#)memalloc.c 5.2 (Berkeley) 3/13/91";
|
#if 0
|
||||||
|
static char sccsid[] = "@(#)memalloc.c 8.3 (Berkeley) 5/4/95";
|
||||||
|
#endif
|
||||||
#endif /* not lint */
|
#endif /* not lint */
|
||||||
|
/*
|
||||||
|
#include <sys/cdefs.h>
|
||||||
|
__FBSDID("$FreeBSD: src/bin/sh/memalloc.c,v 1.26 2004/04/06 20:06:51 markm Exp $");
|
||||||
|
*/
|
||||||
|
|
||||||
#include "shell.h"
|
#include "shell.h"
|
||||||
#include "output.h"
|
#include "output.h"
|
||||||
|
#include "machdep.h"
|
||||||
#include "memalloc.h"
|
#include "memalloc.h"
|
||||||
#include "error.h"
|
#include "error.h"
|
||||||
#include "machdep.h"
|
|
||||||
#include "mystring.h"
|
#include "mystring.h"
|
||||||
|
#include "expand.h"
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Like malloc, but returns an error when out of space.
|
* Like malloc, but returns an error when out of space.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
pointer
|
pointer
|
||||||
ckmalloc(nbytes) {
|
ckmalloc(int nbytes)
|
||||||
register pointer p;
|
{
|
||||||
pointer malloc();
|
pointer p;
|
||||||
|
|
||||||
if ((p = malloc(nbytes)) == NULL)
|
if ((p = malloc(nbytes)) == NULL)
|
||||||
error("Out of space");
|
error("Out of space");
|
||||||
|
@ -65,11 +70,8 @@ ckmalloc(nbytes) {
|
||||||
*/
|
*/
|
||||||
|
|
||||||
pointer
|
pointer
|
||||||
ckrealloc(p, nbytes)
|
ckrealloc(pointer p, int nbytes)
|
||||||
register pointer p;
|
|
||||||
{
|
{
|
||||||
pointer realloc();
|
|
||||||
|
|
||||||
if ((p = realloc(p, nbytes)) == NULL)
|
if ((p = realloc(p, nbytes)) == NULL)
|
||||||
error("Out of space");
|
error("Out of space");
|
||||||
return p;
|
return p;
|
||||||
|
@ -81,10 +83,9 @@ ckrealloc(p, nbytes)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
char *
|
char *
|
||||||
savestr(s)
|
savestr(char *s)
|
||||||
char *s;
|
|
||||||
{
|
{
|
||||||
register char *p;
|
char *p;
|
||||||
|
|
||||||
p = ckmalloc(strlen(s) + 1);
|
p = ckmalloc(strlen(s) + 1);
|
||||||
scopy(s, p);
|
scopy(s, p);
|
||||||
|
@ -97,47 +98,56 @@ savestr(s)
|
||||||
* to make this more efficient, and also to avoid all sorts of exception
|
* to make this more efficient, and also to avoid all sorts of exception
|
||||||
* handling code to handle interrupts in the middle of a parse.
|
* handling code to handle interrupts in the middle of a parse.
|
||||||
*
|
*
|
||||||
* The size 504 was chosen because the Ultrix malloc handles that size
|
* The size 496 was chosen because with 16-byte alignment the total size
|
||||||
* well.
|
* for the allocated block is 512.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define MINSIZE 504 /* minimum size of a block */
|
#define MINSIZE 496 /* minimum size of a block. */
|
||||||
|
|
||||||
|
|
||||||
struct stack_block {
|
struct stack_block {
|
||||||
struct stack_block *prev;
|
struct stack_block *prev;
|
||||||
char space[MINSIZE];
|
/* Data follows */
|
||||||
};
|
};
|
||||||
|
#define SPACE(sp) ((char*)(sp) + ALIGN(sizeof(struct stack_block)))
|
||||||
|
|
||||||
struct stack_block stackbase;
|
STATIC struct stack_block *stackp;
|
||||||
struct stack_block *stackp = &stackbase;
|
STATIC struct stackmark *markp;
|
||||||
char *stacknxt = stackbase.space;
|
char *stacknxt;
|
||||||
int stacknleft = MINSIZE;
|
int stacknleft;
|
||||||
int sstrnleft;
|
int sstrnleft;
|
||||||
int herefd = -1;
|
int herefd = -1;
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
pointer
|
stnewblock(int nbytes)
|
||||||
stalloc(nbytes) {
|
{
|
||||||
register char *p;
|
|
||||||
|
|
||||||
nbytes = ALIGN(nbytes);
|
|
||||||
if (nbytes > stacknleft) {
|
|
||||||
int blocksize;
|
|
||||||
struct stack_block *sp;
|
struct stack_block *sp;
|
||||||
|
int allocsize;
|
||||||
|
|
||||||
|
if (nbytes < MINSIZE)
|
||||||
|
nbytes = MINSIZE;
|
||||||
|
|
||||||
|
allocsize = ALIGN(sizeof(struct stack_block)) + ALIGN(nbytes);
|
||||||
|
|
||||||
blocksize = nbytes;
|
|
||||||
if (blocksize < MINSIZE)
|
|
||||||
blocksize = MINSIZE;
|
|
||||||
INTOFF;
|
INTOFF;
|
||||||
sp = ckmalloc(sizeof(struct stack_block) - MINSIZE + blocksize);
|
sp = ckmalloc(allocsize);
|
||||||
sp->prev = stackp;
|
sp->prev = stackp;
|
||||||
stacknxt = sp->space;
|
stacknxt = SPACE(sp);
|
||||||
stacknleft = blocksize;
|
stacknleft = allocsize - (stacknxt - (char*)sp);
|
||||||
stackp = sp;
|
stackp = sp;
|
||||||
INTON;
|
INTON;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
pointer
|
||||||
|
stalloc(int nbytes)
|
||||||
|
{
|
||||||
|
char *p;
|
||||||
|
|
||||||
|
nbytes = ALIGN(nbytes);
|
||||||
|
if (nbytes > stacknleft)
|
||||||
|
stnewblock(nbytes);
|
||||||
p = stacknxt;
|
p = stacknxt;
|
||||||
stacknxt += nbytes;
|
stacknxt += nbytes;
|
||||||
stacknleft -= nbytes;
|
stacknleft -= nbytes;
|
||||||
|
@ -146,11 +156,10 @@ stalloc(nbytes) {
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
stunalloc(p)
|
stunalloc(pointer p)
|
||||||
pointer p;
|
|
||||||
{
|
{
|
||||||
if (p == NULL) { /*DEBUG */
|
if (p == NULL) { /*DEBUG */
|
||||||
write(2, "stunalloc\n", 10);
|
write(STDERR_FILENO, "stunalloc\n", 10);
|
||||||
abort();
|
abort();
|
||||||
}
|
}
|
||||||
stacknleft += stacknxt - (char *)p;
|
stacknleft += stacknxt - (char *)p;
|
||||||
|
@ -160,22 +169,23 @@ stunalloc(p)
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
setstackmark(mark)
|
setstackmark(struct stackmark *mark)
|
||||||
struct stackmark *mark;
|
|
||||||
{
|
{
|
||||||
mark->stackp = stackp;
|
mark->stackp = stackp;
|
||||||
mark->stacknxt = stacknxt;
|
mark->stacknxt = stacknxt;
|
||||||
mark->stacknleft = stacknleft;
|
mark->stacknleft = stacknleft;
|
||||||
|
mark->marknext = markp;
|
||||||
|
markp = mark;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
popstackmark(mark)
|
popstackmark(struct stackmark *mark)
|
||||||
struct stackmark *mark;
|
|
||||||
{
|
{
|
||||||
struct stack_block *sp;
|
struct stack_block *sp;
|
||||||
|
|
||||||
INTOFF;
|
INTOFF;
|
||||||
|
markp = mark->marknext;
|
||||||
while (stackp != mark->stackp) {
|
while (stackp != mark->stackp) {
|
||||||
sp = stackp;
|
sp = stackp;
|
||||||
stackp = sp->prev;
|
stackp = sp->prev;
|
||||||
|
@ -198,35 +208,56 @@ popstackmark(mark)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void
|
void
|
||||||
growstackblock() {
|
growstackblock(void)
|
||||||
|
{
|
||||||
char *p;
|
char *p;
|
||||||
int newlen = stacknleft * 2 + 100;
|
int newlen;
|
||||||
char *oldspace = stacknxt;
|
char *oldspace;
|
||||||
int oldlen = stacknleft;
|
int oldlen;
|
||||||
struct stack_block *sp;
|
struct stack_block *sp;
|
||||||
|
struct stack_block *oldstackp;
|
||||||
|
struct stackmark *xmark;
|
||||||
|
|
||||||
if (stacknxt == stackp->space && stackp != &stackbase) {
|
newlen = (stacknleft == 0) ? MINSIZE : stacknleft * 2 + 100;
|
||||||
|
newlen = ALIGN(newlen);
|
||||||
|
oldspace = stacknxt;
|
||||||
|
oldlen = stacknleft;
|
||||||
|
|
||||||
|
if (stackp != NULL && stacknxt == SPACE(stackp)) {
|
||||||
INTOFF;
|
INTOFF;
|
||||||
sp = stackp;
|
oldstackp = stackp;
|
||||||
stackp = sp->prev;
|
stackp = oldstackp->prev;
|
||||||
sp = ckrealloc((pointer)sp, sizeof(struct stack_block) - MINSIZE + newlen);
|
sp = ckrealloc((pointer)oldstackp, newlen);
|
||||||
sp->prev = stackp;
|
sp->prev = stackp;
|
||||||
stackp = sp;
|
stackp = sp;
|
||||||
stacknxt = sp->space;
|
stacknxt = SPACE(sp);
|
||||||
stacknleft = newlen;
|
stacknleft = newlen - (stacknxt - (char*)sp);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Stack marks pointing to the start of the old block
|
||||||
|
* must be relocated to point to the new block
|
||||||
|
*/
|
||||||
|
xmark = markp;
|
||||||
|
while (xmark != NULL && xmark->stackp == oldstackp) {
|
||||||
|
xmark->stackp = stackp;
|
||||||
|
xmark->stacknxt = stacknxt;
|
||||||
|
xmark->stacknleft = stacknleft;
|
||||||
|
xmark = xmark->marknext;
|
||||||
|
}
|
||||||
INTON;
|
INTON;
|
||||||
} else {
|
} else {
|
||||||
p = stalloc(newlen);
|
p = stalloc(newlen);
|
||||||
bcopy(oldspace, p, oldlen);
|
if (oldlen != 0)
|
||||||
stacknxt = p; /* free the space */
|
memcpy(p, oldspace, oldlen);
|
||||||
stacknleft += newlen; /* we just allocated */
|
stunalloc(p);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
grabstackblock(len) {
|
grabstackblock(int len)
|
||||||
|
{
|
||||||
len = ALIGN(len);
|
len = ALIGN(len);
|
||||||
stacknxt += len;
|
stacknxt += len;
|
||||||
stacknleft -= len;
|
stacknleft -= len;
|
||||||
|
@ -254,8 +285,11 @@ grabstackblock(len) {
|
||||||
|
|
||||||
|
|
||||||
char *
|
char *
|
||||||
growstackstr() {
|
growstackstr(void)
|
||||||
int len = stackblocksize();
|
{
|
||||||
|
int len;
|
||||||
|
|
||||||
|
len = stackblocksize();
|
||||||
if (herefd >= 0 && len >= 1024) {
|
if (herefd >= 0 && len >= 1024) {
|
||||||
xwrite(herefd, stackblock(), len);
|
xwrite(herefd, stackblock(), len);
|
||||||
sstrnleft = len - 1;
|
sstrnleft = len - 1;
|
||||||
|
@ -272,8 +306,11 @@ growstackstr() {
|
||||||
*/
|
*/
|
||||||
|
|
||||||
char *
|
char *
|
||||||
makestrspace() {
|
makestrspace(void)
|
||||||
int len = stackblocksize() - sstrnleft;
|
{
|
||||||
|
int len;
|
||||||
|
|
||||||
|
len = stackblocksize() - sstrnleft;
|
||||||
growstackblock();
|
growstackblock();
|
||||||
sstrnleft = stackblocksize() - len;
|
sstrnleft = stackblocksize() - len;
|
||||||
return stackblock() + len;
|
return stackblock() + len;
|
||||||
|
@ -282,11 +319,13 @@ makestrspace() {
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
ungrabstackstr(s, p)
|
ungrabstackstr(char *s, char *p)
|
||||||
char *s;
|
|
||||||
char *p;
|
|
||||||
{
|
{
|
||||||
stacknleft += stacknxt - s;
|
stacknleft += stacknxt - s;
|
||||||
stacknxt = s;
|
stacknxt = s;
|
||||||
sstrnleft = stacknleft - (p - s);
|
sstrnleft = stacknleft - (p - s);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* $PchId: memalloc.c,v 1.5 2006/05/22 12:03:26 philip Exp $
|
||||||
|
*/
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/*-
|
/*-
|
||||||
* Copyright (c) 1991 The Regents of the University of California.
|
* Copyright (c) 1991, 1993
|
||||||
* All rights reserved.
|
* The Regents of the University of California. All rights reserved.
|
||||||
*
|
*
|
||||||
* This code is derived from software contributed to Berkeley by
|
* This code is derived from software contributed to Berkeley by
|
||||||
* Kenneth Almquist.
|
* Kenneth Almquist.
|
||||||
|
@ -13,10 +13,6 @@
|
||||||
* 2. Redistributions in binary form must reproduce the above copyright
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
* notice, this list of conditions and the following disclaimer in the
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
* documentation and/or other materials provided with the distribution.
|
* documentation and/or other materials provided with the distribution.
|
||||||
* 3. All advertising materials mentioning features or use of this software
|
|
||||||
* must display the following acknowledgement:
|
|
||||||
* This product includes software developed by the University of
|
|
||||||
* California, Berkeley and its contributors.
|
|
||||||
* 4. Neither the name of the University nor the names of its contributors
|
* 4. Neither the name of the University nor the names of its contributors
|
||||||
* may be used to endorse or promote products derived from this software
|
* may be used to endorse or promote products derived from this software
|
||||||
* without specific prior written permission.
|
* without specific prior written permission.
|
||||||
|
@ -33,13 +29,15 @@
|
||||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||||
* SUCH DAMAGE.
|
* SUCH DAMAGE.
|
||||||
*
|
*
|
||||||
* @(#)memalloc.h 5.1 (Berkeley) 3/7/91
|
* @(#)memalloc.h 8.2 (Berkeley) 5/4/95
|
||||||
|
* $FreeBSD: src/bin/sh/memalloc.h,v 1.9 2004/04/06 20:06:51 markm Exp $
|
||||||
*/
|
*/
|
||||||
|
|
||||||
struct stackmark {
|
struct stackmark {
|
||||||
struct stack_block *stackp;
|
struct stack_block *stackp;
|
||||||
char *stacknxt;
|
char *stacknxt;
|
||||||
int stacknleft;
|
int stacknleft;
|
||||||
|
struct stackmark *marknext;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -48,10 +46,8 @@ extern int stacknleft;
|
||||||
extern int sstrnleft;
|
extern int sstrnleft;
|
||||||
extern int herefd;
|
extern int herefd;
|
||||||
|
|
||||||
#ifdef __STDC__
|
|
||||||
pointer ckmalloc(int);
|
pointer ckmalloc(int);
|
||||||
pointer ckrealloc(pointer, int);
|
pointer ckrealloc(pointer, int);
|
||||||
void free(pointer); /* defined in C library */
|
|
||||||
char *savestr(char *);
|
char *savestr(char *);
|
||||||
pointer stalloc(int);
|
pointer stalloc(int);
|
||||||
void stunalloc(pointer);
|
void stunalloc(pointer);
|
||||||
|
@ -62,21 +58,6 @@ void grabstackblock(int);
|
||||||
char *growstackstr(void);
|
char *growstackstr(void);
|
||||||
char *makestrspace(void);
|
char *makestrspace(void);
|
||||||
void ungrabstackstr(char *, char *);
|
void ungrabstackstr(char *, char *);
|
||||||
#else
|
|
||||||
pointer ckmalloc();
|
|
||||||
pointer ckrealloc();
|
|
||||||
void free(); /* defined in C library */
|
|
||||||
char *savestr();
|
|
||||||
pointer stalloc();
|
|
||||||
void stunalloc();
|
|
||||||
void setstackmark();
|
|
||||||
void popstackmark();
|
|
||||||
void growstackblock();
|
|
||||||
void grabstackblock();
|
|
||||||
char *growstackstr();
|
|
||||||
char *makestrspace();
|
|
||||||
void ungrabstackstr();
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -84,7 +65,7 @@ void ungrabstackstr();
|
||||||
#define stackblocksize() stacknleft
|
#define stackblocksize() stacknleft
|
||||||
#define STARTSTACKSTR(p) p = stackblock(), sstrnleft = stackblocksize()
|
#define STARTSTACKSTR(p) p = stackblock(), sstrnleft = stackblocksize()
|
||||||
#define STPUTC(c, p) (--sstrnleft >= 0? (*p++ = (c)) : (p = growstackstr(), *p++ = (c)))
|
#define STPUTC(c, p) (--sstrnleft >= 0? (*p++ = (c)) : (p = growstackstr(), *p++ = (c)))
|
||||||
#define CHECKSTRSPACE(n, p) if (sstrnleft < n) p = makestrspace(); else
|
#define CHECKSTRSPACE(n, p) { if (sstrnleft < n) p = makestrspace(); }
|
||||||
#define USTPUTC(c, p) (--sstrnleft, *p++ = (c))
|
#define USTPUTC(c, p) (--sstrnleft, *p++ = (c))
|
||||||
#define STACKSTRNUL(p) (sstrnleft == 0? (p = growstackstr(), *p = '\0') : (*p = '\0'))
|
#define STACKSTRNUL(p) (sstrnleft == 0? (p = growstackstr(), *p = '\0') : (*p = '\0'))
|
||||||
#define STUNPUTC(p) (++sstrnleft, --p)
|
#define STUNPUTC(p) (++sstrnleft, --p)
|
||||||
|
@ -93,3 +74,7 @@ void ungrabstackstr();
|
||||||
#define grabstackstr(p) stalloc(stackblocksize() - sstrnleft)
|
#define grabstackstr(p) stalloc(stackblocksize() - sstrnleft)
|
||||||
|
|
||||||
#define ckfree(p) free((pointer)(p))
|
#define ckfree(p) free((pointer)(p))
|
||||||
|
|
||||||
|
/*
|
||||||
|
* $PchId: memalloc.h,v 1.3 2006/03/30 11:39:41 philip Exp $
|
||||||
|
*/
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/*-
|
/*-
|
||||||
* Copyright (c) 1991 The Regents of the University of California.
|
* Copyright (c) 1991, 1993
|
||||||
* All rights reserved.
|
* The Regents of the University of California. All rights reserved.
|
||||||
*
|
*
|
||||||
* This code is derived from software contributed to Berkeley by
|
* This code is derived from software contributed to Berkeley by
|
||||||
* Kenneth Almquist.
|
* Kenneth Almquist.
|
||||||
|
@ -13,10 +13,6 @@
|
||||||
* 2. Redistributions in binary form must reproduce the above copyright
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
* notice, this list of conditions and the following disclaimer in the
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
* documentation and/or other materials provided with the distribution.
|
* documentation and/or other materials provided with the distribution.
|
||||||
* 3. All advertising materials mentioning features or use of this software
|
|
||||||
* must display the following acknowledgement:
|
|
||||||
* This product includes software developed by the University of
|
|
||||||
* California, Berkeley and its contributors.
|
|
||||||
* 4. Neither the name of the University nor the names of its contributors
|
* 4. Neither the name of the University nor the names of its contributors
|
||||||
* may be used to endorse or promote products derived from this software
|
* may be used to endorse or promote products derived from this software
|
||||||
* without specific prior written permission.
|
* without specific prior written permission.
|
||||||
|
@ -35,13 +31,32 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef lint
|
#ifndef lint
|
||||||
static char sccsid[] = "@(#)miscbltin.c 5.2 (Berkeley) 3/13/91";
|
#if 0
|
||||||
|
static char sccsid[] = "@(#)miscbltin.c 8.4 (Berkeley) 5/4/95";
|
||||||
|
#endif
|
||||||
#endif /* not lint */
|
#endif /* not lint */
|
||||||
|
/*
|
||||||
|
#include <sys/cdefs.h>
|
||||||
|
__FBSDID("$FreeBSD: src/bin/sh/miscbltin.c,v 1.30 2004/04/06 20:06:51 markm Exp $");
|
||||||
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Miscelaneous builtins.
|
* Miscellaneous builtins.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <sys/time.h>
|
||||||
|
#include <sys/select.h>
|
||||||
|
#include <time.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <ctype.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <termios.h>
|
||||||
|
|
||||||
#include "shell.h"
|
#include "shell.h"
|
||||||
#include "options.h"
|
#include "options.h"
|
||||||
#include "var.h"
|
#include "var.h"
|
||||||
|
@ -49,38 +64,71 @@ static char sccsid[] = "@(#)miscbltin.c 5.2 (Berkeley) 3/13/91";
|
||||||
#include "memalloc.h"
|
#include "memalloc.h"
|
||||||
#include "error.h"
|
#include "error.h"
|
||||||
#include "mystring.h"
|
#include "mystring.h"
|
||||||
|
#include "builtins.h"
|
||||||
|
|
||||||
#undef eflag
|
#undef eflag
|
||||||
|
|
||||||
extern char **argptr; /* argument list for builtin command */
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The read builtin. The -e option causes backslashes to escape the
|
* The read builtin. The -r option causes backslashes to be treated like
|
||||||
* following character.
|
* ordinary characters.
|
||||||
*
|
*
|
||||||
* This uses unbuffered input, which may be avoidable in some cases.
|
* This uses unbuffered input, which may be avoidable in some cases.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
readcmd(argc, argv) char **argv; {
|
int
|
||||||
|
readcmd(int argc __unused, char **argv __unused)
|
||||||
|
{
|
||||||
char **ap;
|
char **ap;
|
||||||
int backslash;
|
int backslash;
|
||||||
char c;
|
char c;
|
||||||
int eflag;
|
int rflag;
|
||||||
char *prompt;
|
char *prompt;
|
||||||
char *ifs;
|
char *ifs;
|
||||||
char *p;
|
char *p;
|
||||||
int startword;
|
int startword;
|
||||||
int status;
|
int status;
|
||||||
int i;
|
int i;
|
||||||
|
struct timeval tv;
|
||||||
|
char *tvptr;
|
||||||
|
#ifndef __minix_vmd
|
||||||
|
fd_set ifds;
|
||||||
|
#endif
|
||||||
|
struct termios told, tnew;
|
||||||
|
int tsaved;
|
||||||
|
|
||||||
eflag = 0;
|
rflag = 0;
|
||||||
prompt = NULL;
|
prompt = NULL;
|
||||||
while ((i = nextopt("ep:")) != '\0') {
|
tv.tv_sec = -1;
|
||||||
if (i == 'p')
|
tv.tv_usec = 0;
|
||||||
prompt = optarg;
|
while ((i = nextopt("erp:t:")) != '\0') {
|
||||||
else
|
switch(i) {
|
||||||
eflag = 1;
|
case 'p':
|
||||||
|
prompt = shoptarg;
|
||||||
|
break;
|
||||||
|
case 'e':
|
||||||
|
break;
|
||||||
|
case 'r':
|
||||||
|
rflag = 1;
|
||||||
|
break;
|
||||||
|
case 't':
|
||||||
|
tv.tv_sec = strtol(shoptarg, &tvptr, 0);
|
||||||
|
if (tvptr == shoptarg)
|
||||||
|
error("timeout value");
|
||||||
|
switch(*tvptr) {
|
||||||
|
case 0:
|
||||||
|
case 's':
|
||||||
|
break;
|
||||||
|
case 'h':
|
||||||
|
tv.tv_sec *= 60;
|
||||||
|
/* FALLTHROUGH */
|
||||||
|
case 'm':
|
||||||
|
tv.tv_sec *= 60;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
error("timeout unit");
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (prompt && isatty(0)) {
|
if (prompt && isatty(0)) {
|
||||||
out2str(prompt);
|
out2str(prompt);
|
||||||
|
@ -90,12 +138,45 @@ readcmd(argc, argv) char **argv; {
|
||||||
error("arg count");
|
error("arg count");
|
||||||
if ((ifs = bltinlookup("IFS", 1)) == NULL)
|
if ((ifs = bltinlookup("IFS", 1)) == NULL)
|
||||||
ifs = nullstr;
|
ifs = nullstr;
|
||||||
|
|
||||||
|
if (tv.tv_sec >= 0) {
|
||||||
|
#ifdef __minix
|
||||||
|
abort();
|
||||||
|
#else
|
||||||
|
/*
|
||||||
|
* See if we can disable input processing; this will
|
||||||
|
* not give the desired result if we are in a pipeline
|
||||||
|
* and someone upstream is still in line-by-line mode.
|
||||||
|
*/
|
||||||
|
tsaved = 0;
|
||||||
|
if (tcgetattr(0, &told) == 0) {
|
||||||
|
memcpy(&tnew, &told, sizeof(told));
|
||||||
|
cfmakeraw(&tnew);
|
||||||
|
tcsetattr(0, TCSANOW, &tnew);
|
||||||
|
tsaved = 1;
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
* Wait for something to become available.
|
||||||
|
*/
|
||||||
|
FD_ZERO(&ifds);
|
||||||
|
FD_SET(0, &ifds);
|
||||||
|
status = select(1, &ifds, NULL, NULL, &tv);
|
||||||
|
if (tsaved)
|
||||||
|
tcsetattr(0, TCSANOW, &told);
|
||||||
|
/*
|
||||||
|
* If there's nothing ready, return an error.
|
||||||
|
*/
|
||||||
|
if (status <= 0)
|
||||||
|
return(1);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
status = 0;
|
status = 0;
|
||||||
startword = 1;
|
startword = 1;
|
||||||
backslash = 0;
|
backslash = 0;
|
||||||
STARTSTACKSTR(p);
|
STARTSTACKSTR(p);
|
||||||
for (;;) {
|
for (;;) {
|
||||||
if (read(0, &c, 1) != 1) {
|
if (read(STDIN_FILENO, &c, 1) != 1) {
|
||||||
status = 1;
|
status = 1;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -107,7 +188,7 @@ readcmd(argc, argv) char **argv; {
|
||||||
STPUTC(c, p);
|
STPUTC(c, p);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (eflag && c == '\\') {
|
if (!rflag && c == '\\') {
|
||||||
backslash++;
|
backslash++;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -118,7 +199,7 @@ readcmd(argc, argv) char **argv; {
|
||||||
}
|
}
|
||||||
startword = 0;
|
startword = 0;
|
||||||
if (backslash && c == '\\') {
|
if (backslash && c == '\\') {
|
||||||
if (read(0, &c, 1) != 1) {
|
if (read(STDIN_FILENO, &c, 1) != 1) {
|
||||||
status = 1;
|
status = 1;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -142,25 +223,274 @@ readcmd(argc, argv) char **argv; {
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
umaskcmd(argc, argv) char **argv; {
|
int
|
||||||
|
umaskcmd(int argc __unused, char **argv)
|
||||||
|
{
|
||||||
|
char *ap;
|
||||||
int mask;
|
int mask;
|
||||||
char *p;
|
|
||||||
int i;
|
int i;
|
||||||
|
int symbolic_mode = 0;
|
||||||
|
|
||||||
|
while ((i = nextopt("S")) != '\0') {
|
||||||
|
symbolic_mode = 1;
|
||||||
|
}
|
||||||
|
|
||||||
if ((p = argv[1]) == NULL) {
|
|
||||||
INTOFF;
|
INTOFF;
|
||||||
mask = umask(0);
|
mask = umask(0);
|
||||||
umask(mask);
|
umask(mask);
|
||||||
INTON;
|
INTON;
|
||||||
out1fmt("%.4o\n", mask); /* %#o might be better */
|
|
||||||
|
if ((ap = *argptr) == NULL) {
|
||||||
|
if (symbolic_mode) {
|
||||||
|
char u[4], g[4], o[4];
|
||||||
|
|
||||||
|
i = 0;
|
||||||
|
if ((mask & S_IRUSR) == 0)
|
||||||
|
u[i++] = 'r';
|
||||||
|
if ((mask & S_IWUSR) == 0)
|
||||||
|
u[i++] = 'w';
|
||||||
|
if ((mask & S_IXUSR) == 0)
|
||||||
|
u[i++] = 'x';
|
||||||
|
u[i] = '\0';
|
||||||
|
|
||||||
|
i = 0;
|
||||||
|
if ((mask & S_IRGRP) == 0)
|
||||||
|
g[i++] = 'r';
|
||||||
|
if ((mask & S_IWGRP) == 0)
|
||||||
|
g[i++] = 'w';
|
||||||
|
if ((mask & S_IXGRP) == 0)
|
||||||
|
g[i++] = 'x';
|
||||||
|
g[i] = '\0';
|
||||||
|
|
||||||
|
i = 0;
|
||||||
|
if ((mask & S_IROTH) == 0)
|
||||||
|
o[i++] = 'r';
|
||||||
|
if ((mask & S_IWOTH) == 0)
|
||||||
|
o[i++] = 'w';
|
||||||
|
if ((mask & S_IXOTH) == 0)
|
||||||
|
o[i++] = 'x';
|
||||||
|
o[i] = '\0';
|
||||||
|
|
||||||
|
out1fmt("u=%s,g=%s,o=%s\n", u, g, o);
|
||||||
} else {
|
} else {
|
||||||
|
out1fmt("%.4o\n", mask);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (isdigit(*ap)) {
|
||||||
mask = 0;
|
mask = 0;
|
||||||
do {
|
do {
|
||||||
if ((unsigned)(i = *p - '0') >= 8)
|
if (*ap >= '8' || *ap < '0')
|
||||||
error("Illegal number: %s", argv[1]);
|
error("Illegal number: %s", argv[1]);
|
||||||
mask = (mask << 3) + i;
|
mask = (mask << 3) + (*ap - '0');
|
||||||
} while (*++p != '\0');
|
} while (*++ap != '\0');
|
||||||
umask(mask);
|
umask(mask);
|
||||||
|
} else {
|
||||||
|
void *set;
|
||||||
|
if ((set = setmode (ap)) == 0)
|
||||||
|
error("Illegal number: %s", ap);
|
||||||
|
|
||||||
|
mask = getmode (set, ~mask & 0777);
|
||||||
|
umask(~mask & 0777);
|
||||||
|
free(set);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef __minix
|
||||||
|
struct rlimit
|
||||||
|
{
|
||||||
|
unsigned long rlim_cur; /* current (soft) limit */
|
||||||
|
unsigned long rlim_max; /* maximum value for rlim_cur */
|
||||||
|
};
|
||||||
|
#define RLIM_INFINITY (((unsigned long)1 << 31) - 1)
|
||||||
|
|
||||||
|
int getrlimit (int, struct rlimit *);
|
||||||
|
int setrlimit (int, const struct rlimit *);
|
||||||
|
|
||||||
|
int getrlimit(resource, rlp)
|
||||||
|
int resource;
|
||||||
|
struct rlimit *rlp;
|
||||||
|
{
|
||||||
|
errno= ENOSYS;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
int setrlimit(resource, rlp)
|
||||||
|
int resource;
|
||||||
|
const struct rlimit *rlp;
|
||||||
|
{
|
||||||
|
errno= ENOSYS;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
* ulimit builtin
|
||||||
|
*
|
||||||
|
* This code, originally by Doug Gwyn, Doug Kingston, Eric Gisin, and
|
||||||
|
* Michael Rendell was ripped from pdksh 5.0.8 and hacked for use with
|
||||||
|
* ash by J.T. Conklin.
|
||||||
|
*
|
||||||
|
* Public domain.
|
||||||
|
*/
|
||||||
|
|
||||||
|
struct limits {
|
||||||
|
const char *name;
|
||||||
|
const char *units;
|
||||||
|
int cmd;
|
||||||
|
int factor; /* multiply by to get rlim_{cur,max} values */
|
||||||
|
char option;
|
||||||
|
};
|
||||||
|
|
||||||
|
static const struct limits limits[] = {
|
||||||
|
#ifdef RLIMIT_CPU
|
||||||
|
{ "cpu time", "seconds", RLIMIT_CPU, 1, 't' },
|
||||||
|
#endif
|
||||||
|
#ifdef RLIMIT_FSIZE
|
||||||
|
{ "file size", "512-blocks", RLIMIT_FSIZE, 512, 'f' },
|
||||||
|
#endif
|
||||||
|
#ifdef RLIMIT_DATA
|
||||||
|
{ "data seg size", "kbytes", RLIMIT_DATA, 1024, 'd' },
|
||||||
|
#endif
|
||||||
|
#ifdef RLIMIT_STACK
|
||||||
|
{ "stack size", "kbytes", RLIMIT_STACK, 1024, 's' },
|
||||||
|
#endif
|
||||||
|
#ifdef RLIMIT_CORE
|
||||||
|
{ "core file size", "512-blocks", RLIMIT_CORE, 512, 'c' },
|
||||||
|
#endif
|
||||||
|
#ifdef RLIMIT_RSS
|
||||||
|
{ "max memory size", "kbytes", RLIMIT_RSS, 1024, 'm' },
|
||||||
|
#endif
|
||||||
|
#ifdef RLIMIT_MEMLOCK
|
||||||
|
{ "locked memory", "kbytes", RLIMIT_MEMLOCK, 1024, 'l' },
|
||||||
|
#endif
|
||||||
|
#ifdef RLIMIT_NPROC
|
||||||
|
{ "max user processes", (char *)0, RLIMIT_NPROC, 1, 'u' },
|
||||||
|
#endif
|
||||||
|
#ifdef RLIMIT_NOFILE
|
||||||
|
{ "open files", (char *)0, RLIMIT_NOFILE, 1, 'n' },
|
||||||
|
#endif
|
||||||
|
#ifdef RLIMIT_VMEM
|
||||||
|
{ "virtual mem size", "kbytes", RLIMIT_VMEM, 1024, 'v' },
|
||||||
|
#endif
|
||||||
|
#ifdef RLIMIT_SWAP
|
||||||
|
{ "swap limit", "kbytes", RLIMIT_SWAP, 1024, 'w' },
|
||||||
|
#endif
|
||||||
|
#ifdef RLIMIT_SBSIZE
|
||||||
|
{ "sbsize", "bytes", RLIMIT_SBSIZE, 1, 'b' },
|
||||||
|
#endif
|
||||||
|
{ (char *) 0, (char *)0, 0, 0, '\0' }
|
||||||
|
};
|
||||||
|
|
||||||
|
int
|
||||||
|
ulimitcmd(int argc __unused, char **argv __unused)
|
||||||
|
{
|
||||||
|
int c;
|
||||||
|
intmax_t val = 0;
|
||||||
|
enum { SOFT = 0x1, HARD = 0x2 }
|
||||||
|
how = SOFT | HARD;
|
||||||
|
const struct limits *l;
|
||||||
|
int set, all = 0;
|
||||||
|
int optc, what;
|
||||||
|
struct rlimit limit;
|
||||||
|
|
||||||
|
what = 'f';
|
||||||
|
while ((optc = nextopt("HSatfdsmcnuvlb")) != '\0')
|
||||||
|
switch (optc) {
|
||||||
|
case 'H':
|
||||||
|
how = HARD;
|
||||||
|
break;
|
||||||
|
case 'S':
|
||||||
|
how = SOFT;
|
||||||
|
break;
|
||||||
|
case 'a':
|
||||||
|
all = 1;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
what = optc;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (l = limits; l->name && l->option != what; l++)
|
||||||
|
;
|
||||||
|
if (!l->name)
|
||||||
|
error("internal error (%c)", what);
|
||||||
|
|
||||||
|
set = *argptr ? 1 : 0;
|
||||||
|
if (set) {
|
||||||
|
char *p = *argptr;
|
||||||
|
|
||||||
|
if (all || argptr[1])
|
||||||
|
error("too many arguments");
|
||||||
|
if (strcmp(p, "unlimited") == 0)
|
||||||
|
val = RLIM_INFINITY;
|
||||||
|
else {
|
||||||
|
val = 0;
|
||||||
|
|
||||||
|
while ((c = *p++) >= '0' && c <= '9')
|
||||||
|
{
|
||||||
|
val = (val * 10) + (long)(c - '0');
|
||||||
|
if (val < 0)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (c)
|
||||||
|
error("bad number");
|
||||||
|
val *= l->factor;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (all) {
|
||||||
|
for (l = limits; l->name; l++) {
|
||||||
|
char optbuf[40];
|
||||||
|
if (getrlimit(l->cmd, &limit) < 0)
|
||||||
|
error("can't get limit: %s", strerror(errno));
|
||||||
|
if (how & SOFT)
|
||||||
|
val = limit.rlim_cur;
|
||||||
|
else if (how & HARD)
|
||||||
|
val = limit.rlim_max;
|
||||||
|
|
||||||
|
if (l->units)
|
||||||
|
snprintf(optbuf, sizeof(optbuf),
|
||||||
|
"(%s, -%c) ", l->units, l->option);
|
||||||
|
else
|
||||||
|
snprintf(optbuf, sizeof(optbuf),
|
||||||
|
"(-%c) ", l->option);
|
||||||
|
out1fmt("%-18s %18s ", l->name, optbuf);
|
||||||
|
if (val == RLIM_INFINITY)
|
||||||
|
out1fmt("unlimited\n");
|
||||||
|
else
|
||||||
|
{
|
||||||
|
val /= l->factor;
|
||||||
|
out1fmt("%jd\n", (intmax_t)val);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (getrlimit(l->cmd, &limit) < 0)
|
||||||
|
error("can't get limit: %s", strerror(errno));
|
||||||
|
if (set) {
|
||||||
|
if (how & SOFT)
|
||||||
|
limit.rlim_cur = val;
|
||||||
|
if (how & HARD)
|
||||||
|
limit.rlim_max = val;
|
||||||
|
if (setrlimit(l->cmd, &limit) < 0)
|
||||||
|
error("bad limit: %s", strerror(errno));
|
||||||
|
} else {
|
||||||
|
if (how & SOFT)
|
||||||
|
val = limit.rlim_cur;
|
||||||
|
else if (how & HARD)
|
||||||
|
val = limit.rlim_max;
|
||||||
|
|
||||||
|
if (val == RLIM_INFINITY)
|
||||||
|
out1fmt("unlimited\n");
|
||||||
|
else
|
||||||
|
{
|
||||||
|
val /= l->factor;
|
||||||
|
out1fmt("%jd\n", (intmax_t)val);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* $PchId: miscbltin.c,v 1.7 2006/05/23 11:59:08 philip Exp $
|
||||||
|
*/
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
#!/bin/sh -
|
#!/bin/sh -
|
||||||
#
|
#
|
||||||
# Copyright (c) 1991 The Regents of the University of California.
|
# Copyright (c) 1991, 1993
|
||||||
# All rights reserved.
|
# The Regents of the University of California. All rights reserved.
|
||||||
#
|
#
|
||||||
# This code is derived from software contributed to Berkeley by
|
# This code is derived from software contributed to Berkeley by
|
||||||
# Kenneth Almquist.
|
# Kenneth Almquist.
|
||||||
|
@ -14,10 +14,6 @@
|
||||||
# 2. Redistributions in binary form must reproduce the above copyright
|
# 2. Redistributions in binary form must reproduce the above copyright
|
||||||
# notice, this list of conditions and the following disclaimer in the
|
# notice, this list of conditions and the following disclaimer in the
|
||||||
# documentation and/or other materials provided with the distribution.
|
# documentation and/or other materials provided with the distribution.
|
||||||
# 3. All advertising materials mentioning features or use of this software
|
|
||||||
# must display the following acknowledgement:
|
|
||||||
# This product includes software developed by the University of
|
|
||||||
# California, Berkeley and its contributors.
|
|
||||||
# 4. Neither the name of the University nor the names of its contributors
|
# 4. Neither the name of the University nor the names of its contributors
|
||||||
# may be used to endorse or promote products derived from this software
|
# may be used to endorse or promote products derived from this software
|
||||||
# without specific prior written permission.
|
# without specific prior written permission.
|
||||||
|
@ -34,90 +30,69 @@
|
||||||
# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||||
# SUCH DAMAGE.
|
# SUCH DAMAGE.
|
||||||
#
|
#
|
||||||
# @(#)mkbuiltins 5.2 (Berkeley) 3/8/91
|
# @(#)mkbuiltins 8.2 (Berkeley) 5/4/95
|
||||||
|
# $FreeBSD: src/bin/sh/mkbuiltins,v 1.13 2004/04/06 20:06:51 markm Exp $
|
||||||
|
|
||||||
# All calls to awk removed, because Minix bawk is deficient. (kjb)
|
#temp=`/usr/bin/mktemp -t ka`
|
||||||
|
temp=/tmp/mkb$$
|
||||||
if [ $# != 2 ]
|
havehist=1
|
||||||
then
|
if [ "X$1" = "X-h" ]; then
|
||||||
echo "USAGE: $0 shell.h builtins"
|
havehist=0
|
||||||
exit 1
|
shift
|
||||||
fi
|
fi
|
||||||
SHL=$1
|
havejobs=0
|
||||||
BLTINS=$2
|
if [ "X$1" = "X-j" ]; then
|
||||||
|
havejobs=0
|
||||||
temp=/tmp/ka$$
|
shift
|
||||||
exec > builtins.c
|
elif grep '^#define[ ]*JOBS[ ]*1' $2 > /dev/null
|
||||||
|
then havejobs=1
|
||||||
|
fi
|
||||||
|
objdir=$1
|
||||||
|
exec > ${objdir}/builtins.c
|
||||||
cat <<\!
|
cat <<\!
|
||||||
/*
|
/*
|
||||||
* This file was generated by the mkbuiltins program.
|
* This file was generated by the mkbuiltins program.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
#include "shell.h"
|
#include "shell.h"
|
||||||
#include "builtins.h"
|
#include "builtins.h"
|
||||||
|
|
||||||
!
|
!
|
||||||
if grep '^#define JOBS[ ]*1' $SHL > /dev/null
|
awk '/^[^#]/ {if(('$havejobs' || $2 != "-j") && ('$havehist' || $2 != "-h")) \
|
||||||
then
|
print $0}' $3 | sed 's/-[hj]//' > $temp
|
||||||
# Job control.
|
#awk '{ printf "int %s();\n", $1}' $temp
|
||||||
sed -e '/^#/d
|
|
||||||
s/ / /g
|
|
||||||
s/ #.*//
|
|
||||||
/^ *$/d
|
|
||||||
s/-j//' $BLTINS > $temp
|
|
||||||
else
|
|
||||||
# No job control.
|
|
||||||
sed -e '/^#/d
|
|
||||||
s/ / /g
|
|
||||||
s/ #.*//
|
|
||||||
/^ *$/d
|
|
||||||
/-j/d' $BLTINS > $temp
|
|
||||||
fi
|
|
||||||
sed -e 's/ .*//
|
|
||||||
s/\(.*\)/int \1();/' $temp
|
|
||||||
echo '
|
echo '
|
||||||
int (*const builtinfunc[])() = {'
|
int (*const builtinfunc[]) (int, char **) = {'
|
||||||
sed -e 's/ .*//
|
awk '/^[^#]/ { printf "\t%s,\n", $1}' $temp
|
||||||
s/\(.*\)/ \1,/' $temp
|
|
||||||
echo '};
|
echo '};
|
||||||
|
|
||||||
const struct builtincmd builtincmd[] = {'
|
const struct builtincmd builtincmd[] = {'
|
||||||
i=0
|
awk '{ for (i = 2 ; i <= NF ; i++) {
|
||||||
while read line
|
printf "\t{ \"%s\", %d },\n", $i, NR-1
|
||||||
do
|
}}' $temp
|
||||||
set -$- $line
|
echo ' { NULL, 0 }
|
||||||
shift
|
|
||||||
for fun
|
|
||||||
do
|
|
||||||
echo " \"$fun\", $i,"
|
|
||||||
done
|
|
||||||
i=`expr $i + 1`
|
|
||||||
done < $temp
|
|
||||||
echo ' NULL, 0
|
|
||||||
};'
|
};'
|
||||||
|
|
||||||
exec > builtins.h
|
exec > ${objdir}/builtins.h
|
||||||
cat <<\!
|
cat <<\!
|
||||||
/*
|
/*
|
||||||
* This file was generated by the mkbuiltins program.
|
* This file was generated by the mkbuiltins program.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <sys/cdefs.h>
|
|
||||||
!
|
!
|
||||||
i=0
|
|
||||||
tr abcdefghijklmnopqrstuvwxyz ABCDEFGHIJKLMNOPQRSTUVWXYZ < $temp |
|
tr abcdefghijklmnopqrstuvwxyz ABCDEFGHIJKLMNOPQRSTUVWXYZ < $temp |
|
||||||
while read line
|
awk '{ printf "#define %s %d\n", $1, NR-1}'
|
||||||
do
|
|
||||||
set -$- $line
|
|
||||||
echo "#define $1 $i"
|
|
||||||
i=`expr $i + 1`
|
|
||||||
done
|
|
||||||
echo '
|
echo '
|
||||||
struct builtincmd {
|
struct builtincmd {
|
||||||
char *name;
|
char *name;
|
||||||
int code;
|
int code;
|
||||||
};
|
};
|
||||||
|
|
||||||
extern int (*const builtinfunc[])();
|
extern int (*const builtinfunc[]) (int, char **);
|
||||||
extern const struct builtincmd builtincmd[];'
|
extern const struct builtincmd builtincmd[];'
|
||||||
|
awk '{ printf "int %s (int, char **);\n", $1 }' < $temp
|
||||||
rm -f $temp
|
rm -f $temp
|
||||||
|
|
||||||
|
#
|
||||||
|
# $PchId: mkbuiltins,v 1.6 2006/05/22 12:42:58 philip Exp $
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/*-
|
/*-
|
||||||
* Copyright (c) 1991 The Regents of the University of California.
|
* Copyright (c) 1991, 1993
|
||||||
* All rights reserved.
|
* The Regents of the University of California. All rights reserved.
|
||||||
*
|
*
|
||||||
* This code is derived from software contributed to Berkeley by
|
* This code is derived from software contributed to Berkeley by
|
||||||
* Kenneth Almquist.
|
* Kenneth Almquist.
|
||||||
|
@ -13,10 +13,6 @@
|
||||||
* 2. Redistributions in binary form must reproduce the above copyright
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
* notice, this list of conditions and the following disclaimer in the
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
* documentation and/or other materials provided with the distribution.
|
* documentation and/or other materials provided with the distribution.
|
||||||
* 3. All advertising materials mentioning features or use of this software
|
|
||||||
* must display the following acknowledgement:
|
|
||||||
* This product includes software developed by the University of
|
|
||||||
* California, Berkeley and its contributors.
|
|
||||||
* 4. Neither the name of the University nor the names of its contributors
|
* 4. Neither the name of the University nor the names of its contributors
|
||||||
* may be used to endorse or promote products derived from this software
|
* may be used to endorse or promote products derived from this software
|
||||||
* without specific prior written permission.
|
* without specific prior written permission.
|
||||||
|
@ -35,43 +31,51 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef lint
|
#ifndef lint
|
||||||
char copyright[] =
|
static char const copyright[] =
|
||||||
"@(#) Copyright (c) 1991 The Regents of the University of California.\n\
|
"@(#) Copyright (c) 1991, 1993\n\
|
||||||
All rights reserved.\n";
|
The Regents of the University of California. All rights reserved.\n";
|
||||||
#endif /* not lint */
|
#endif /* not lint */
|
||||||
|
|
||||||
#ifndef lint
|
#ifndef lint
|
||||||
static char sccsid[] = "@(#)mkinit.c 5.3 (Berkeley) 3/13/91";
|
#if 0
|
||||||
|
static char sccsid[] = "@(#)mkinit.c 8.2 (Berkeley) 5/4/95";
|
||||||
|
#endif
|
||||||
#endif /* not lint */
|
#endif /* not lint */
|
||||||
|
/*
|
||||||
|
#include <sys/cdefs.h>
|
||||||
|
__FBSDID("$FreeBSD: src/bin/sh/mkinit.c,v 1.17 2004/04/06 20:06:51 markm Exp $");
|
||||||
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This program scans all the source files for code to handle various
|
* This program scans all the source files for code to handle various
|
||||||
* special events and combines this code into one file. This (allegedly)
|
* special events and combines this code into one file. This (allegedly)
|
||||||
* improves the structure of the program since there is no need for
|
* improves the structure of the program since there is no need for
|
||||||
* anyone outside of a module to know that that module performs special
|
* anyone outside of a module to know that that module performs special
|
||||||
* operations on particular events. The command is executed iff init.c
|
* operations on particular events.
|
||||||
* is actually changed.
|
|
||||||
*
|
*
|
||||||
* Usage: mkinit command sourcefile...
|
* Usage: mkinit sourcefile...
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
#include <sys/cdefs.h>
|
|
||||||
|
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <errno.h>
|
||||||
|
|
||||||
|
#ifdef __minix
|
||||||
|
#define __unused
|
||||||
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* OUTFILE is the name of the output file. Output is initially written
|
* OUTFILE is the name of the output file. Output is initially written
|
||||||
* to the file OUTTEMP, which is then moved to OUTFILE if OUTTEMP and
|
* to the file OUTTEMP, which is then moved to OUTFILE.
|
||||||
* OUTFILE are different.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define OUTFILE "init.c"
|
#define OUTFILE "init.c"
|
||||||
#define OUTTEMP "init.c.new"
|
#define OUTTEMP "init.c.new"
|
||||||
#define OUTOBJ "init.o"
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -148,42 +152,35 @@ struct text decls; /* declarations */
|
||||||
int amiddecls; /* for formatting */
|
int amiddecls; /* for formatting */
|
||||||
|
|
||||||
|
|
||||||
void readfile(), doevent(), doinclude(), dodecl(), output();
|
static void readfile(char *);
|
||||||
void addstr(), addchar(), writetext();
|
static int match(char *, char *);
|
||||||
|
static int gooddefine(char *);
|
||||||
|
static void doevent(struct event *, FILE *, char *);
|
||||||
|
static void doinclude(char *);
|
||||||
|
static void dodecl(char *, FILE *);
|
||||||
|
static void output(void);
|
||||||
|
static void addstr(char *, struct text *);
|
||||||
|
static void addchar(int, struct text *);
|
||||||
|
static void writetext(struct text *, FILE *);
|
||||||
|
static FILE *ckfopen(char *, char *);
|
||||||
|
static void *ckmalloc(int);
|
||||||
|
static char *savestr(char *);
|
||||||
|
static void error(char *);
|
||||||
|
|
||||||
#define equal(s1, s2) (strcmp(s1, s2) == 0)
|
#define equal(s1, s2) (strcmp(s1, s2) == 0)
|
||||||
|
|
||||||
FILE *ckfopen();
|
int
|
||||||
char *savestr();
|
main(int argc __unused, char *argv[])
|
||||||
void *ckmalloc __P((int));
|
|
||||||
void error();
|
|
||||||
|
|
||||||
main(argc, argv)
|
|
||||||
char **argv;
|
|
||||||
{
|
{
|
||||||
char **ap;
|
char **ap;
|
||||||
int fd;
|
|
||||||
char c;
|
|
||||||
|
|
||||||
if (argc < 2)
|
|
||||||
error("Usage: mkinit command file...");
|
|
||||||
header_files[0] = "\"shell.h\"";
|
header_files[0] = "\"shell.h\"";
|
||||||
header_files[1] = "\"mystring.h\"";
|
header_files[1] = "\"mystring.h\"";
|
||||||
for (ap = argv + 2 ; *ap ; ap++)
|
for (ap = argv + 1 ; *ap ; ap++)
|
||||||
readfile(*ap);
|
readfile(*ap);
|
||||||
output();
|
output();
|
||||||
if (file_changed()) {
|
rename(OUTTEMP, OUTFILE);
|
||||||
unlink(OUTFILE);
|
exit(0);
|
||||||
link(OUTTEMP, OUTFILE);
|
|
||||||
unlink(OUTTEMP);
|
|
||||||
} else {
|
|
||||||
unlink(OUTTEMP);
|
|
||||||
if (touch(OUTOBJ))
|
|
||||||
exit(0); /* no compilation necessary */
|
|
||||||
}
|
|
||||||
printf("%s\n", argv[1]);
|
|
||||||
execl("/bin/sh", "sh", "-c", argv[1], (char *)0);
|
|
||||||
error("Can't exec shell");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -191,9 +188,8 @@ main(argc, argv)
|
||||||
* Parse an input file.
|
* Parse an input file.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void
|
static void
|
||||||
readfile(fname)
|
readfile(char *fname)
|
||||||
char *fname;
|
|
||||||
{
|
{
|
||||||
FILE *fp;
|
FILE *fp;
|
||||||
char line[1024];
|
char line[1024];
|
||||||
|
@ -215,19 +211,31 @@ readfile(fname)
|
||||||
doinclude(line);
|
doinclude(line);
|
||||||
if (line[0] == 'M' && match("MKINIT", line))
|
if (line[0] == 'M' && match("MKINIT", line))
|
||||||
dodecl(line, fp);
|
dodecl(line, fp);
|
||||||
if (line[0] == '#' && gooddefine(line))
|
if (line[0] == '#' && gooddefine(line)) {
|
||||||
|
char *cp;
|
||||||
|
char line2[1024];
|
||||||
|
static const char undef[] = "#undef ";
|
||||||
|
|
||||||
|
strcpy(line2, line);
|
||||||
|
memcpy(line2, undef, sizeof(undef) - 1);
|
||||||
|
cp = line2 + sizeof(undef) - 1;
|
||||||
|
while(*cp && (*cp == ' ' || *cp == '\t'))
|
||||||
|
cp++;
|
||||||
|
while(*cp && *cp != ' ' && *cp != '\t' && *cp != '\n')
|
||||||
|
cp++;
|
||||||
|
*cp++ = '\n'; *cp = '\0';
|
||||||
|
addstr(line2, &defines);
|
||||||
addstr(line, &defines);
|
addstr(line, &defines);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
fclose(fp);
|
fclose(fp);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int
|
static int
|
||||||
match(name, line)
|
match(char *name, char *line)
|
||||||
char *name;
|
|
||||||
char *line;
|
|
||||||
{
|
{
|
||||||
register char *p, *q;
|
char *p, *q;
|
||||||
|
|
||||||
p = name, q = line;
|
p = name, q = line;
|
||||||
while (*p) {
|
while (*p) {
|
||||||
|
@ -240,11 +248,10 @@ match(name, line)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int
|
static int
|
||||||
gooddefine(line)
|
gooddefine(char *line)
|
||||||
char *line;
|
|
||||||
{
|
{
|
||||||
register char *p;
|
char *p;
|
||||||
|
|
||||||
if (! match("#define", line))
|
if (! match("#define", line))
|
||||||
return 0; /* not a define */
|
return 0; /* not a define */
|
||||||
|
@ -264,11 +271,8 @@ gooddefine(line)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
static void
|
||||||
doevent(ep, fp, fname)
|
doevent(struct event *ep, FILE *fp, char *fname)
|
||||||
register struct event *ep;
|
|
||||||
FILE *fp;
|
|
||||||
char *fname;
|
|
||||||
{
|
{
|
||||||
char line[1024];
|
char line[1024];
|
||||||
int indent;
|
int indent;
|
||||||
|
@ -304,13 +308,12 @@ doevent(ep, fp, fname)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
static void
|
||||||
doinclude(line)
|
doinclude(char *line)
|
||||||
char *line;
|
|
||||||
{
|
{
|
||||||
register char *p;
|
char *p;
|
||||||
char *name;
|
char *name;
|
||||||
register char **pp;
|
char **pp;
|
||||||
|
|
||||||
for (p = line ; *p != '"' && *p != '<' && *p != '\0' ; p++);
|
for (p = line ; *p != '"' && *p != '<' && *p != '\0' ; p++);
|
||||||
if (*p == '\0')
|
if (*p == '\0')
|
||||||
|
@ -329,13 +332,11 @@ doinclude(line)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
static void
|
||||||
dodecl(line1, fp)
|
dodecl(char *line1, FILE *fp)
|
||||||
char *line1;
|
|
||||||
FILE *fp;
|
|
||||||
{
|
{
|
||||||
char line[1024];
|
char line[1024];
|
||||||
register char *p, *q;
|
char *p, *q;
|
||||||
|
|
||||||
if (strcmp(line1, "MKINIT\n") == 0) { /* start of struct/union decl */
|
if (strcmp(line1, "MKINIT\n") == 0) { /* start of struct/union decl */
|
||||||
addchar('\n', &decls);
|
addchar('\n', &decls);
|
||||||
|
@ -350,7 +351,8 @@ dodecl(line1, fp)
|
||||||
if (! amiddecls)
|
if (! amiddecls)
|
||||||
addchar('\n', &decls);
|
addchar('\n', &decls);
|
||||||
q = NULL;
|
q = NULL;
|
||||||
for (p = line1 + 6 ; *p != '=' && *p != '/' ; p++);
|
for (p = line1 + 6 ; *p && strchr("=/\n", *p) == NULL; p++)
|
||||||
|
continue;
|
||||||
if (*p == '=') { /* eliminate initialization */
|
if (*p == '=') { /* eliminate initialization */
|
||||||
for (q = p ; *q && *q != ';' ; q++);
|
for (q = p ; *q && *q != ';' ; q++);
|
||||||
if (*q == '\0')
|
if (*q == '\0')
|
||||||
|
@ -375,8 +377,9 @@ dodecl(line1, fp)
|
||||||
* Write the output to the file OUTTEMP.
|
* Write the output to the file OUTTEMP.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void
|
static void
|
||||||
output() {
|
output(void)
|
||||||
|
{
|
||||||
FILE *fp;
|
FILE *fp;
|
||||||
char **pp;
|
char **pp;
|
||||||
struct event *ep;
|
struct event *ep;
|
||||||
|
@ -392,7 +395,7 @@ output() {
|
||||||
for (ep = event ; ep->name ; ep++) {
|
for (ep = event ; ep->name ; ep++) {
|
||||||
fputs("\n\n\n", fp);
|
fputs("\n\n\n", fp);
|
||||||
fputs(ep->comment, fp);
|
fputs(ep->comment, fp);
|
||||||
fprintf(fp, "\nvoid\n%s() {\n", ep->routine);
|
fprintf(fp, "\nvoid\n%s(void) {\n", ep->routine);
|
||||||
writetext(&ep->code, fp);
|
writetext(&ep->code, fp);
|
||||||
fprintf(fp, "}\n");
|
fprintf(fp, "}\n");
|
||||||
}
|
}
|
||||||
|
@ -400,61 +403,14 @@ output() {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Return true if the new output file is different from the old one.
|
|
||||||
*/
|
|
||||||
|
|
||||||
int
|
|
||||||
file_changed() {
|
|
||||||
register FILE *f1, *f2;
|
|
||||||
register int c;
|
|
||||||
|
|
||||||
if ((f1 = fopen(OUTFILE, "r")) == NULL
|
|
||||||
|| (f2 = fopen(OUTTEMP, "r")) == NULL)
|
|
||||||
return 1;
|
|
||||||
while ((c = getc(f1)) == getc(f2)) {
|
|
||||||
if (c == EOF)
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Touch a file. Returns 0 on failure, 1 on success.
|
|
||||||
*/
|
|
||||||
|
|
||||||
int
|
|
||||||
touch(file)
|
|
||||||
char *file;
|
|
||||||
{
|
|
||||||
int fd;
|
|
||||||
char c;
|
|
||||||
|
|
||||||
if ((fd = open(file, O_RDWR)) < 0)
|
|
||||||
return 0;
|
|
||||||
if (read(fd, &c, 1) != 1) {
|
|
||||||
close(fd);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
lseek(fd, 0L, 0);
|
|
||||||
write(fd, &c, 1);
|
|
||||||
close(fd);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* A text structure is simply a block of text that is kept in memory.
|
* A text structure is simply a block of text that is kept in memory.
|
||||||
* Addstr appends a string to the text struct, and addchar appends a single
|
* Addstr appends a string to the text struct, and addchar appends a single
|
||||||
* character.
|
* character.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void
|
static void
|
||||||
addstr(s, text)
|
addstr(char *s, struct text *text)
|
||||||
register char *s;
|
|
||||||
register struct text *text;
|
|
||||||
{
|
{
|
||||||
while (*s) {
|
while (*s) {
|
||||||
if (--text->nleft < 0)
|
if (--text->nleft < 0)
|
||||||
|
@ -465,9 +421,8 @@ addstr(s, text)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
static void
|
||||||
addchar(c, text)
|
addchar(int c, struct text *text)
|
||||||
register struct text *text;
|
|
||||||
{
|
{
|
||||||
struct block *bp;
|
struct block *bp;
|
||||||
|
|
||||||
|
@ -487,10 +442,8 @@ addchar(c, text)
|
||||||
/*
|
/*
|
||||||
* Write the contents of a text structure to a file.
|
* Write the contents of a text structure to a file.
|
||||||
*/
|
*/
|
||||||
void
|
static void
|
||||||
writetext(text, fp)
|
writetext(struct text *text, FILE *fp)
|
||||||
struct text *text;
|
|
||||||
FILE *fp;
|
|
||||||
{
|
{
|
||||||
struct block *bp;
|
struct block *bp;
|
||||||
|
|
||||||
|
@ -501,47 +454,47 @@ writetext(text, fp)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
FILE *
|
static FILE *
|
||||||
ckfopen(file, mode)
|
ckfopen(char *file, char *mode)
|
||||||
char *file;
|
|
||||||
char *mode;
|
|
||||||
{
|
{
|
||||||
FILE *fp;
|
FILE *fp;
|
||||||
|
|
||||||
if ((fp = fopen(file, mode)) == NULL) {
|
if ((fp = fopen(file, mode)) == NULL) {
|
||||||
fprintf(stderr, "Can't open %s\n", file);
|
fprintf(stderr, "Can't open %s: %s\n", file, strerror(errno));
|
||||||
exit(2);
|
exit(2);
|
||||||
}
|
}
|
||||||
return fp;
|
return fp;
|
||||||
}
|
}
|
||||||
|
|
||||||
void *
|
static void *
|
||||||
ckmalloc(nbytes) {
|
ckmalloc(int nbytes)
|
||||||
register char *p;
|
{
|
||||||
char *malloc();
|
char *p;
|
||||||
|
|
||||||
if ((p = malloc(nbytes)) == NULL)
|
if ((p = malloc(nbytes)) == NULL)
|
||||||
error("Out of space");
|
error("Out of space");
|
||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
|
|
||||||
char *
|
static char *
|
||||||
savestr(s)
|
savestr(char *s)
|
||||||
char *s;
|
|
||||||
{
|
{
|
||||||
register char *p;
|
char *p;
|
||||||
|
|
||||||
p = ckmalloc(strlen(s) + 1);
|
p = ckmalloc(strlen(s) + 1);
|
||||||
strcpy(p, s);
|
strcpy(p, s);
|
||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
static void
|
||||||
error(msg)
|
error(char *msg)
|
||||||
char *msg;
|
|
||||||
{
|
{
|
||||||
if (curfile != NULL)
|
if (curfile != NULL)
|
||||||
fprintf(stderr, "%s:%d: ", curfile, linno);
|
fprintf(stderr, "%s:%d: ", curfile, linno);
|
||||||
fprintf(stderr, "%s\n", msg);
|
fprintf(stderr, "%s\n", msg);
|
||||||
exit(2);
|
exit(2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* $PchId: mkinit.c,v 1.6 2006/05/22 12:16:50 philip Exp $
|
||||||
|
*/
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/*-
|
/*-
|
||||||
* Copyright (c) 1991 The Regents of the University of California.
|
* Copyright (c) 1991, 1993
|
||||||
* All rights reserved.
|
* The Regents of the University of California. All rights reserved.
|
||||||
*
|
*
|
||||||
* This code is derived from software contributed to Berkeley by
|
* This code is derived from software contributed to Berkeley by
|
||||||
* Kenneth Almquist.
|
* Kenneth Almquist.
|
||||||
|
@ -13,10 +13,6 @@
|
||||||
* 2. Redistributions in binary form must reproduce the above copyright
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
* notice, this list of conditions and the following disclaimer in the
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
* documentation and/or other materials provided with the distribution.
|
* documentation and/or other materials provided with the distribution.
|
||||||
* 3. All advertising materials mentioning features or use of this software
|
|
||||||
* must display the following acknowledgement:
|
|
||||||
* This product includes software developed by the University of
|
|
||||||
* California, Berkeley and its contributors.
|
|
||||||
* 4. Neither the name of the University nor the names of its contributors
|
* 4. Neither the name of the University nor the names of its contributors
|
||||||
* may be used to endorse or promote products derived from this software
|
* may be used to endorse or promote products derived from this software
|
||||||
* without specific prior written permission.
|
* without specific prior written permission.
|
||||||
|
@ -34,15 +30,20 @@
|
||||||
* SUCH DAMAGE.
|
* SUCH DAMAGE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#if 0
|
||||||
#ifndef lint
|
#ifndef lint
|
||||||
char copyright[] =
|
static char const copyright[] =
|
||||||
"@(#) Copyright (c) 1991 The Regents of the University of California.\n\
|
"@(#) Copyright (c) 1991, 1993\n\
|
||||||
All rights reserved.\n";
|
The Regents of the University of California. All rights reserved.\n";
|
||||||
#endif /* not lint */
|
#endif /* not lint */
|
||||||
|
|
||||||
#ifndef lint
|
#ifndef lint
|
||||||
static char sccsid[] = "@(#)mknodes.c 5.1 (Berkeley) 3/7/91";
|
static char sccsid[] = "@(#)mknodes.c 8.2 (Berkeley) 5/4/95";
|
||||||
#endif /* not lint */
|
#endif /* not lint */
|
||||||
|
#endif
|
||||||
|
/*
|
||||||
|
__FBSDID("$FreeBSD: src/bin/sh/mknodes.c,v 1.17 2004/04/06 20:06:51 markm Exp $");
|
||||||
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This program reads the nodetypes file and nodes.c.pat file. It generates
|
* This program reads the nodetypes file and nodes.c.pat file. It generates
|
||||||
|
@ -50,7 +51,10 @@ static char sccsid[] = "@(#)mknodes.c 5.1 (Berkeley) 3/7/91";
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <stdarg.h>
|
||||||
|
|
||||||
#define MAXTYPES 50 /* max number of node types */
|
#define MAXTYPES 50 /* max number of node types */
|
||||||
#define MAXFIELDS 20 /* max fields in a structure */
|
#define MAXFIELDS 20 /* max fields in a structure */
|
||||||
|
@ -80,31 +84,42 @@ struct str { /* struct representing a node structure */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
int ntypes; /* number of node types */
|
static int ntypes; /* number of node types */
|
||||||
char *nodename[MAXTYPES]; /* names of the nodes */
|
static char *nodename[MAXTYPES]; /* names of the nodes */
|
||||||
struct str *nodestr[MAXTYPES]; /* type of structure used by the node */
|
static struct str *nodestr[MAXTYPES]; /* type of structure used by the node */
|
||||||
int nstr; /* number of structures */
|
static int nstr; /* number of structures */
|
||||||
struct str str[MAXTYPES]; /* the structures */
|
static struct str str[MAXTYPES]; /* the structures */
|
||||||
struct str *curstr; /* current structure */
|
static struct str *curstr; /* current structure */
|
||||||
|
static FILE *infp;
|
||||||
|
static char line[1024];
|
||||||
|
static int linno;
|
||||||
|
static char *linep;
|
||||||
|
|
||||||
|
#ifndef __printf0like
|
||||||
|
#define __printf0like(a,b)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static void parsenode(void);
|
||||||
|
static void parsefield(void);
|
||||||
|
static void output(char *);
|
||||||
|
static void outsizes(FILE *);
|
||||||
|
static void outfunc(FILE *, int);
|
||||||
|
static void indent(int, FILE *);
|
||||||
|
static int nextfield(char *);
|
||||||
|
static void skipbl(void);
|
||||||
|
static int readline(void);
|
||||||
|
static void error(const char *, ...) __printf0like(1, 2);
|
||||||
|
static char *savestr(const char *);
|
||||||
|
|
||||||
|
|
||||||
FILE *infp = stdin;
|
int
|
||||||
char line[1024];
|
main(int argc, char *argv[])
|
||||||
int linno;
|
|
||||||
char *linep;
|
|
||||||
|
|
||||||
|
|
||||||
char *savestr();
|
|
||||||
#define equal(s1, s2) (strcmp(s1, s2) == 0)
|
|
||||||
|
|
||||||
|
|
||||||
main(argc, argv)
|
|
||||||
char **argv;
|
|
||||||
{
|
{
|
||||||
if (argc != 3)
|
if (argc != 3)
|
||||||
error("usage: mknodes file\n");
|
error("usage: mknodes file");
|
||||||
|
infp = stdin;
|
||||||
if ((infp = fopen(argv[1], "r")) == NULL)
|
if ((infp = fopen(argv[1], "r")) == NULL)
|
||||||
error("Can't open %s", argv[1]);
|
error("Can't open %s: %s", argv[1], strerror(errno));
|
||||||
while (readline()) {
|
while (readline()) {
|
||||||
if (line[0] == ' ' || line[0] == '\t')
|
if (line[0] == ' ' || line[0] == '\t')
|
||||||
parsefield();
|
parsefield();
|
||||||
|
@ -112,12 +127,14 @@ main(argc, argv)
|
||||||
parsenode();
|
parsenode();
|
||||||
}
|
}
|
||||||
output(argv[2]);
|
output(argv[2]);
|
||||||
return 0;
|
exit(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
parsenode() {
|
static void
|
||||||
|
parsenode(void)
|
||||||
|
{
|
||||||
char name[BUFLEN];
|
char name[BUFLEN];
|
||||||
char tag[BUFLEN];
|
char tag[BUFLEN];
|
||||||
struct str *sp;
|
struct str *sp;
|
||||||
|
@ -131,7 +148,7 @@ parsenode() {
|
||||||
error("Garbage at end of line");
|
error("Garbage at end of line");
|
||||||
nodename[ntypes] = savestr(name);
|
nodename[ntypes] = savestr(name);
|
||||||
for (sp = str ; sp < str + nstr ; sp++) {
|
for (sp = str ; sp < str + nstr ; sp++) {
|
||||||
if (equal(sp->tag, tag))
|
if (strcmp(sp->tag, tag) == 0)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (sp >= str + nstr) {
|
if (sp >= str + nstr) {
|
||||||
|
@ -145,7 +162,9 @@ parsenode() {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
parsefield() {
|
static void
|
||||||
|
parsefield(void)
|
||||||
|
{
|
||||||
char name[BUFLEN];
|
char name[BUFLEN];
|
||||||
char type[BUFLEN];
|
char type[BUFLEN];
|
||||||
char decl[2 * BUFLEN];
|
char decl[2 * BUFLEN];
|
||||||
|
@ -159,21 +178,21 @@ parsefield() {
|
||||||
error("No field type");
|
error("No field type");
|
||||||
fp = &curstr->field[curstr->nfields];
|
fp = &curstr->field[curstr->nfields];
|
||||||
fp->name = savestr(name);
|
fp->name = savestr(name);
|
||||||
if (equal(type, "nodeptr")) {
|
if (strcmp(type, "nodeptr") == 0) {
|
||||||
fp->type = T_NODE;
|
fp->type = T_NODE;
|
||||||
sprintf(decl, "union node *%s", name);
|
sprintf(decl, "union node *%s", name);
|
||||||
} else if (equal(type, "nodelist")) {
|
} else if (strcmp(type, "nodelist") == 0) {
|
||||||
fp->type = T_NODELIST;
|
fp->type = T_NODELIST;
|
||||||
sprintf(decl, "struct nodelist *%s", name);
|
sprintf(decl, "struct nodelist *%s", name);
|
||||||
} else if (equal(type, "string")) {
|
} else if (strcmp(type, "string") == 0) {
|
||||||
fp->type = T_STRING;
|
fp->type = T_STRING;
|
||||||
sprintf(decl, "char *%s", name);
|
sprintf(decl, "char *%s", name);
|
||||||
} else if (equal(type, "int")) {
|
} else if (strcmp(type, "int") == 0) {
|
||||||
fp->type = T_INT;
|
fp->type = T_INT;
|
||||||
sprintf(decl, "int %s", name);
|
sprintf(decl, "int %s", name);
|
||||||
} else if (equal(type, "other")) {
|
} else if (strcmp(type, "other") == 0) {
|
||||||
fp->type = T_OTHER;
|
fp->type = T_OTHER;
|
||||||
} else if (equal(type, "temp")) {
|
} else if (strcmp(type, "temp") == 0) {
|
||||||
fp->type = T_TEMP;
|
fp->type = T_TEMP;
|
||||||
} else {
|
} else {
|
||||||
error("Unknown type %s", type);
|
error("Unknown type %s", type);
|
||||||
|
@ -196,8 +215,8 @@ char writer[] = "\
|
||||||
*/\n\
|
*/\n\
|
||||||
\n";
|
\n";
|
||||||
|
|
||||||
output(file)
|
static void
|
||||||
char *file;
|
output(char *file)
|
||||||
{
|
{
|
||||||
FILE *hfile;
|
FILE *hfile;
|
||||||
FILE *cfile;
|
FILE *cfile;
|
||||||
|
@ -208,9 +227,9 @@ output(file)
|
||||||
char *p;
|
char *p;
|
||||||
|
|
||||||
if ((patfile = fopen(file, "r")) == NULL)
|
if ((patfile = fopen(file, "r")) == NULL)
|
||||||
error("Can't open %s", file);
|
error("Can't open %s: %s", file, strerror(errno));
|
||||||
if ((hfile = fopen("nodes.h", "w")) == NULL)
|
if ((hfile = fopen("nodes.h", "w")) == NULL)
|
||||||
error("Can't create nodes.h");
|
error("Can't create nodes.h: %s", strerror(errno));
|
||||||
if ((cfile = fopen("nodes.c", "w")) == NULL)
|
if ((cfile = fopen("nodes.c", "w")) == NULL)
|
||||||
error("Can't create nodes.c");
|
error("Can't create nodes.c");
|
||||||
fputs(writer, hfile);
|
fputs(writer, hfile);
|
||||||
|
@ -234,22 +253,17 @@ output(file)
|
||||||
fputs("\tstruct nodelist *next;\n", hfile);
|
fputs("\tstruct nodelist *next;\n", hfile);
|
||||||
fputs("\tunion node *n;\n", hfile);
|
fputs("\tunion node *n;\n", hfile);
|
||||||
fputs("};\n\n\n", hfile);
|
fputs("};\n\n\n", hfile);
|
||||||
fputs("#ifdef __STDC__\n", hfile);
|
|
||||||
fputs("union node *copyfunc(union node *);\n", hfile);
|
fputs("union node *copyfunc(union node *);\n", hfile);
|
||||||
fputs("void freefunc(union node *);\n", hfile);
|
fputs("void freefunc(union node *);\n", hfile);
|
||||||
fputs("#else\n", hfile);
|
|
||||||
fputs("union node *copyfunc();\n", hfile);
|
|
||||||
fputs("void freefunc();\n", hfile);
|
|
||||||
fputs("#endif\n", hfile);
|
|
||||||
|
|
||||||
fputs(writer, cfile);
|
fputs(writer, cfile);
|
||||||
while (fgets(line, sizeof line, patfile) != NULL) {
|
while (fgets(line, sizeof line, patfile) != NULL) {
|
||||||
for (p = line ; *p == ' ' || *p == '\t' ; p++);
|
for (p = line ; *p == ' ' || *p == '\t' ; p++);
|
||||||
if (equal(p, "%SIZES\n"))
|
if (strcmp(p, "%SIZES\n") == 0)
|
||||||
outsizes(cfile);
|
outsizes(cfile);
|
||||||
else if (equal(p, "%CALCSIZE\n"))
|
else if (strcmp(p, "%CALCSIZE\n") == 0)
|
||||||
outfunc(cfile, 1);
|
outfunc(cfile, 1);
|
||||||
else if (equal(p, "%COPY\n"))
|
else if (strcmp(p, "%COPY\n") == 0)
|
||||||
outfunc(cfile, 0);
|
outfunc(cfile, 0);
|
||||||
else
|
else
|
||||||
fputs(line, cfile);
|
fputs(line, cfile);
|
||||||
|
@ -258,8 +272,8 @@ output(file)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
outsizes(cfile)
|
static void
|
||||||
FILE *cfile;
|
outsizes(FILE *cfile)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
|
@ -271,8 +285,8 @@ outsizes(cfile)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
outfunc(cfile, calcsize)
|
static void
|
||||||
FILE *cfile;
|
outfunc(FILE *cfile, int calcsize)
|
||||||
{
|
{
|
||||||
struct str *sp;
|
struct str *sp;
|
||||||
struct field *fp;
|
struct field *fp;
|
||||||
|
@ -287,8 +301,7 @@ outfunc(cfile, calcsize)
|
||||||
fputs(" funcblocksize += nodesize[n->type];\n", cfile);
|
fputs(" funcblocksize += nodesize[n->type];\n", cfile);
|
||||||
else {
|
else {
|
||||||
fputs(" new = funcblock;\n", cfile);
|
fputs(" new = funcblock;\n", cfile);
|
||||||
fputs(" *(char **)&funcblock += nodesize[n->type];\n",
|
fputs(" funcblock = (char *)funcblock + nodesize[n->type];\n", cfile);
|
||||||
cfile);
|
|
||||||
}
|
}
|
||||||
fputs(" switch (n->type) {\n", cfile);
|
fputs(" switch (n->type) {\n", cfile);
|
||||||
for (sp = str ; sp < &str[nstr] ; sp++) {
|
for (sp = str ; sp < &str[nstr] ; sp++) {
|
||||||
|
@ -351,8 +364,8 @@ outfunc(cfile, calcsize)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
indent(amount, fp)
|
static void
|
||||||
FILE *fp;
|
indent(int amount, FILE *fp)
|
||||||
{
|
{
|
||||||
while (amount >= 8) {
|
while (amount >= 8) {
|
||||||
putc('\t', fp);
|
putc('\t', fp);
|
||||||
|
@ -364,11 +377,10 @@ indent(amount, fp)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int
|
static int
|
||||||
nextfield(buf)
|
nextfield(char *buf)
|
||||||
char *buf;
|
|
||||||
{
|
{
|
||||||
register char *p, *q;
|
char *p, *q;
|
||||||
|
|
||||||
p = linep;
|
p = linep;
|
||||||
while (*p == ' ' || *p == '\t')
|
while (*p == ' ' || *p == '\t')
|
||||||
|
@ -382,15 +394,18 @@ nextfield(buf)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
skipbl() {
|
static void
|
||||||
|
skipbl(void)
|
||||||
|
{
|
||||||
while (*linep == ' ' || *linep == '\t')
|
while (*linep == ' ' || *linep == '\t')
|
||||||
linep++;
|
linep++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int
|
static int
|
||||||
readline() {
|
readline(void)
|
||||||
register char *p;
|
{
|
||||||
|
char *p;
|
||||||
|
|
||||||
if (fgets(line, 1024, infp) == NULL)
|
if (fgets(line, 1024, infp) == NULL)
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -407,26 +422,34 @@ readline() {
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
error(msg, a1, a2, a3, a4, a5, a6)
|
static void
|
||||||
char *msg;
|
error(const char *msg, ...)
|
||||||
{
|
{
|
||||||
fprintf(stderr, "line %d: ", linno);
|
va_list va;
|
||||||
fprintf(stderr, msg, a1, a2, a3, a4, a5, a6);
|
va_start(va, msg);
|
||||||
putc('\n', stderr);
|
|
||||||
|
(void) fprintf(stderr, "line %d: ", linno);
|
||||||
|
(void) vfprintf(stderr, msg, va);
|
||||||
|
(void) fputc('\n', stderr);
|
||||||
|
|
||||||
|
va_end(va);
|
||||||
|
|
||||||
exit(2);
|
exit(2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
char *
|
static char *
|
||||||
savestr(s)
|
savestr(const char *s)
|
||||||
char *s;
|
|
||||||
{
|
{
|
||||||
register char *p;
|
char *p;
|
||||||
char *malloc();
|
|
||||||
|
|
||||||
if ((p = malloc(strlen(s) + 1)) == NULL)
|
if ((p = malloc(strlen(s) + 1)) == NULL)
|
||||||
error("Out of space");
|
error("Out of space");
|
||||||
strcpy(p, s);
|
(void) strcpy(p, s);
|
||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* $PchId: mknodes.c,v 1.6 2006/05/23 12:05:14 philip Exp $
|
||||||
|
*/
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/*-
|
/*-
|
||||||
* Copyright (c) 1991 The Regents of the University of California.
|
* Copyright (c) 1991, 1993
|
||||||
* All rights reserved.
|
* The Regents of the University of California. All rights reserved.
|
||||||
*
|
*
|
||||||
* This code is derived from software contributed to Berkeley by
|
* This code is derived from software contributed to Berkeley by
|
||||||
* Kenneth Almquist.
|
* Kenneth Almquist.
|
||||||
|
@ -35,23 +35,23 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef lint
|
#ifndef lint
|
||||||
char copyright[] =
|
static char copyright[] =
|
||||||
"@(#) Copyright (c) 1991 The Regents of the University of California.\n\
|
"@(#) Copyright (c) 1991, 1993\n\
|
||||||
All rights reserved.\n";
|
The Regents of the University of California. All rights reserved.\n";
|
||||||
#endif /* not lint */
|
#endif /* not lint */
|
||||||
|
|
||||||
#ifndef lint
|
#ifndef lint
|
||||||
static char sccsid[] = "@(#)mksignames.c 5.1 (Berkeley) 3/7/91";
|
static char sccsid[] = "@(#)mksignames.c 8.1 (Berkeley) 5/31/93";
|
||||||
#endif /* not lint */
|
#endif /* not lint */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This program generates the signames.h and signames.c files.
|
* This program generates the signames.h and signames.c files.
|
||||||
*/
|
*/
|
||||||
#include <sys/types.h>
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
|
|
||||||
|
int main(int argc, char *argv[]);
|
||||||
|
|
||||||
struct sig {
|
struct sig {
|
||||||
int signo; /* signal number */
|
int signo; /* signal number */
|
||||||
|
@ -198,3 +198,7 @@ main(argc, argv) char **argv; {
|
||||||
fprintf(cfile, "};\n");
|
fprintf(cfile, "};\n");
|
||||||
exit(0);
|
exit(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* $PchId: mksignames.c,v 1.2 2001/05/14 19:22:26 philip Exp $
|
||||||
|
*/
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/*-
|
/*-
|
||||||
* Copyright (c) 1991 The Regents of the University of California.
|
* Copyright (c) 1991, 1993
|
||||||
* All rights reserved.
|
* The Regents of the University of California. All rights reserved.
|
||||||
*
|
*
|
||||||
* This code is derived from software contributed to Berkeley by
|
* This code is derived from software contributed to Berkeley by
|
||||||
* Kenneth Almquist.
|
* Kenneth Almquist.
|
||||||
|
@ -13,10 +13,6 @@
|
||||||
* 2. Redistributions in binary form must reproduce the above copyright
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
* notice, this list of conditions and the following disclaimer in the
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
* documentation and/or other materials provided with the distribution.
|
* documentation and/or other materials provided with the distribution.
|
||||||
* 3. All advertising materials mentioning features or use of this software
|
|
||||||
* must display the following acknowledgement:
|
|
||||||
* This product includes software developed by the University of
|
|
||||||
* California, Berkeley and its contributors.
|
|
||||||
* 4. Neither the name of the University nor the names of its contributors
|
* 4. Neither the name of the University nor the names of its contributors
|
||||||
* may be used to endorse or promote products derived from this software
|
* may be used to endorse or promote products derived from this software
|
||||||
* without specific prior written permission.
|
* without specific prior written permission.
|
||||||
|
@ -34,23 +30,33 @@
|
||||||
* SUCH DAMAGE.
|
* SUCH DAMAGE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#if 0
|
||||||
#ifndef lint
|
#ifndef lint
|
||||||
char copyright[] =
|
static char const copyright[] =
|
||||||
"@(#) Copyright (c) 1991 The Regents of the University of California.\n\
|
"@(#) Copyright (c) 1991, 1993\n\
|
||||||
All rights reserved.\n";
|
The Regents of the University of California. All rights reserved.\n";
|
||||||
#endif /* not lint */
|
#endif /* not lint */
|
||||||
|
|
||||||
#ifndef lint
|
#ifndef lint
|
||||||
static char sccsid[] = "@(#)mksyntax.c 5.2 (Berkeley) 3/8/91";
|
static char sccsid[] = "@(#)mksyntax.c 8.2 (Berkeley) 5/4/95";
|
||||||
#endif /* not lint */
|
#endif /* not lint */
|
||||||
|
#endif
|
||||||
|
/*
|
||||||
|
__FBSDID("$FreeBSD: src/bin/sh/mksyntax.c,v 1.23 2004/04/06 20:06:51 markm Exp $");
|
||||||
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This program creates syntax.h and syntax.c.
|
* This program creates syntax.h and syntax.c.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
#include "parser.h"
|
#include "parser.h"
|
||||||
|
|
||||||
|
#ifdef __minix
|
||||||
|
#define __unused
|
||||||
|
#endif
|
||||||
|
|
||||||
struct synclass {
|
struct synclass {
|
||||||
char *name;
|
char *name;
|
||||||
|
@ -59,19 +65,21 @@ struct synclass {
|
||||||
|
|
||||||
/* Syntax classes */
|
/* Syntax classes */
|
||||||
struct synclass synclass[] = {
|
struct synclass synclass[] = {
|
||||||
"CWORD", "character is nothing special",
|
{ "CWORD", "character is nothing special" },
|
||||||
"CNL", "newline character",
|
{ "CNL", "newline character" },
|
||||||
"CBACK", "a backslash character",
|
{ "CBACK", "a backslash character" },
|
||||||
"CSQUOTE", "single quote",
|
{ "CSQUOTE", "single quote" },
|
||||||
"CDQUOTE", "double quote",
|
{ "CDQUOTE", "double quote" },
|
||||||
"CENDQUOTE", "a terminating quote",
|
{ "CENDQUOTE", "a terminating quote" },
|
||||||
"CBQUOTE", "backwards single quote",
|
{ "CBQUOTE", "backwards single quote" },
|
||||||
"CVAR", "a dollar sign",
|
{ "CVAR", "a dollar sign" },
|
||||||
"CENDVAR", "a '}' character",
|
{ "CENDVAR", "a '}' character" },
|
||||||
"CEOF", "end of file",
|
{ "CLP", "a left paren in arithmetic" },
|
||||||
"CCTL", "like CWORD, except it must be escaped",
|
{ "CRP", "a right paren in arithmetic" },
|
||||||
"CSPCL", "these terminate a word",
|
{ "CEOF", "end of file" },
|
||||||
NULL, NULL
|
{ "CCTL", "like CWORD, except it must be escaped" },
|
||||||
|
{ "CSPCL", "these terminate a word" },
|
||||||
|
{ NULL, NULL }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -80,31 +88,39 @@ struct synclass synclass[] = {
|
||||||
* you may have to change the definition of the is_in_name macro.
|
* you may have to change the definition of the is_in_name macro.
|
||||||
*/
|
*/
|
||||||
struct synclass is_entry[] = {
|
struct synclass is_entry[] = {
|
||||||
"ISDIGIT", "a digit",
|
{ "ISDIGIT", "a digit" },
|
||||||
"ISUPPER", "an upper case letter",
|
{ "ISUPPER", "an upper case letter" },
|
||||||
"ISLOWER", "a lower case letter",
|
{ "ISLOWER", "a lower case letter" },
|
||||||
"ISUNDER", "an underscore",
|
{ "ISUNDER", "an underscore" },
|
||||||
"ISSPECL", "the name of a special parameter",
|
{ "ISSPECL", "the name of a special parameter" },
|
||||||
NULL, NULL,
|
{ NULL, NULL }
|
||||||
};
|
};
|
||||||
|
|
||||||
char writer[] = "\
|
static char writer[] = "\
|
||||||
/*\n\
|
/*\n\
|
||||||
* This file was generated by the mksyntax program.\n\
|
* This file was generated by the mksyntax program.\n\
|
||||||
*/\n\
|
*/\n\
|
||||||
\n";
|
\n";
|
||||||
|
|
||||||
|
|
||||||
FILE *cfile;
|
static FILE *cfile;
|
||||||
FILE *hfile;
|
static FILE *hfile;
|
||||||
char *syntax[513];
|
static char *syntax[513];
|
||||||
int base;
|
static int base;
|
||||||
int size; /* number of values which a char variable can have */
|
static int size; /* number of values which a char variable can have */
|
||||||
int nbits; /* number of bits in a character */
|
static int nbits; /* number of bits in a character */
|
||||||
int digit_contig; /* true if digits are contiguous */
|
static int digit_contig;/* true if digits are contiguous */
|
||||||
|
|
||||||
|
static void filltable(char *);
|
||||||
|
static void init(void);
|
||||||
|
static void add(char *, char *);
|
||||||
|
static void print(char *);
|
||||||
|
static void output_type_macros(void);
|
||||||
|
static void digit_convert(void);
|
||||||
|
|
||||||
main() {
|
int
|
||||||
|
main(int argc __unused, char **argv __unused)
|
||||||
|
{
|
||||||
char c;
|
char c;
|
||||||
char d;
|
char d;
|
||||||
int sign;
|
int sign;
|
||||||
|
@ -136,7 +152,9 @@ main() {
|
||||||
if (d == c)
|
if (d == c)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
#if 0
|
||||||
printf("%s %d bit chars\n", sign? "signed" : "unsigned", nbits);
|
printf("%s %d bit chars\n", sign? "signed" : "unsigned", nbits);
|
||||||
|
#endif
|
||||||
if (nbits > 9) {
|
if (nbits > 9) {
|
||||||
fputs("Characters can't have more than 9 bits\n", stderr);
|
fputs("Characters can't have more than 9 bits\n", stderr);
|
||||||
exit(2);
|
exit(2);
|
||||||
|
@ -151,14 +169,14 @@ main() {
|
||||||
digit_contig = 0;
|
digit_contig = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
fputs("#include <sys/cdefs.h>\n", hfile);
|
fputs("#include <ctype.h>\n", hfile);
|
||||||
|
|
||||||
/* Generate the #define statements in the header file */
|
/* Generate the #define statements in the header file */
|
||||||
fputs("/* Syntax classes */\n", hfile);
|
fputs("/* Syntax classes */\n", hfile);
|
||||||
for (i = 0 ; synclass[i].name ; i++) {
|
for (i = 0 ; synclass[i].name ; i++) {
|
||||||
sprintf(buf, "#define %s %d", synclass[i].name, i);
|
sprintf(buf, "#define %s %d", synclass[i].name, i);
|
||||||
fputs(buf, hfile);
|
fputs(buf, hfile);
|
||||||
for (pos = strlen(buf) ; pos < 32 ; pos = pos + 8 &~ 07)
|
for (pos = strlen(buf) ; pos < 32 ; pos = (pos + 8) & ~07)
|
||||||
putc('\t', hfile);
|
putc('\t', hfile);
|
||||||
fprintf(hfile, "/* %s */\n", synclass[i].comment);
|
fprintf(hfile, "/* %s */\n", synclass[i].comment);
|
||||||
}
|
}
|
||||||
|
@ -167,7 +185,7 @@ main() {
|
||||||
for (i = 0 ; is_entry[i].name ; i++) {
|
for (i = 0 ; is_entry[i].name ; i++) {
|
||||||
sprintf(buf, "#define %s %#o", is_entry[i].name, 1 << i);
|
sprintf(buf, "#define %s %#o", is_entry[i].name, 1 << i);
|
||||||
fputs(buf, hfile);
|
fputs(buf, hfile);
|
||||||
for (pos = strlen(buf) ; pos < 32 ; pos = pos + 8 &~ 07)
|
for (pos = strlen(buf) ; pos < 32 ; pos = (pos + 8) & ~07)
|
||||||
putc('\t', hfile);
|
putc('\t', hfile);
|
||||||
fprintf(hfile, "/* %s */\n", is_entry[i].comment);
|
fprintf(hfile, "/* %s */\n", is_entry[i].comment);
|
||||||
}
|
}
|
||||||
|
@ -178,6 +196,7 @@ main() {
|
||||||
fputs("#define BASESYNTAX (basesyntax + SYNBASE)\n", hfile);
|
fputs("#define BASESYNTAX (basesyntax + SYNBASE)\n", hfile);
|
||||||
fputs("#define DQSYNTAX (dqsyntax + SYNBASE)\n", hfile);
|
fputs("#define DQSYNTAX (dqsyntax + SYNBASE)\n", hfile);
|
||||||
fputs("#define SQSYNTAX (sqsyntax + SYNBASE)\n", hfile);
|
fputs("#define SQSYNTAX (sqsyntax + SYNBASE)\n", hfile);
|
||||||
|
fputs("#define ARISYNTAX (arisyntax + SYNBASE)\n", hfile);
|
||||||
putc('\n', hfile);
|
putc('\n', hfile);
|
||||||
output_type_macros(); /* is_digit, etc. */
|
output_type_macros(); /* is_digit, etc. */
|
||||||
putc('\n', hfile);
|
putc('\n', hfile);
|
||||||
|
@ -204,14 +223,28 @@ main() {
|
||||||
add("`", "CBQUOTE");
|
add("`", "CBQUOTE");
|
||||||
add("$", "CVAR");
|
add("$", "CVAR");
|
||||||
add("}", "CENDVAR");
|
add("}", "CENDVAR");
|
||||||
add("!*?[=", "CCTL");
|
/* ':/' for tilde expansion, '-' for [a\-x] pattern ranges */
|
||||||
|
add("!*?[=~:/-", "CCTL");
|
||||||
print("dqsyntax");
|
print("dqsyntax");
|
||||||
init();
|
init();
|
||||||
fputs("\n/* syntax table used when in single quotes */\n", cfile);
|
fputs("\n/* syntax table used when in single quotes */\n", cfile);
|
||||||
add("\n", "CNL");
|
add("\n", "CNL");
|
||||||
add("'", "CENDQUOTE");
|
add("'", "CENDQUOTE");
|
||||||
add("!*?[=", "CCTL");
|
/* ':/' for tilde expansion, '-' for [a\-x] pattern ranges */
|
||||||
|
add("!*?[=~:/-", "CCTL");
|
||||||
print("sqsyntax");
|
print("sqsyntax");
|
||||||
|
init();
|
||||||
|
fputs("\n/* syntax table used when in arithmetic */\n", cfile);
|
||||||
|
add("\n", "CNL");
|
||||||
|
add("\\", "CBACK");
|
||||||
|
add("`", "CBQUOTE");
|
||||||
|
add("'", "CSQUOTE");
|
||||||
|
add("\"", "CDQUOTE");
|
||||||
|
add("$", "CVAR");
|
||||||
|
add("}", "CENDVAR");
|
||||||
|
add("(", "CLP");
|
||||||
|
add(")", "CRP");
|
||||||
|
print("arisyntax");
|
||||||
filltable("0");
|
filltable("0");
|
||||||
fputs("\n/* character classification table */\n", cfile);
|
fputs("\n/* character classification table */\n", cfile);
|
||||||
add("0123456789", "ISDIGIT");
|
add("0123456789", "ISDIGIT");
|
||||||
|
@ -231,8 +264,8 @@ main() {
|
||||||
* Clear the syntax table.
|
* Clear the syntax table.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
filltable(dftval)
|
static void
|
||||||
char *dftval;
|
filltable(char *dftval)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
|
@ -245,7 +278,9 @@ filltable(dftval)
|
||||||
* Initialize the syntax table with default values.
|
* Initialize the syntax table with default values.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
init() {
|
static void
|
||||||
|
init(void)
|
||||||
|
{
|
||||||
filltable("CWORD");
|
filltable("CWORD");
|
||||||
syntax[0] = "CEOF";
|
syntax[0] = "CEOF";
|
||||||
syntax[base + CTLESC] = "CCTL";
|
syntax[base + CTLESC] = "CCTL";
|
||||||
|
@ -253,6 +288,9 @@ init() {
|
||||||
syntax[base + CTLENDVAR] = "CCTL";
|
syntax[base + CTLENDVAR] = "CCTL";
|
||||||
syntax[base + CTLBACKQ] = "CCTL";
|
syntax[base + CTLBACKQ] = "CCTL";
|
||||||
syntax[base + CTLBACKQ + CTLQUOTE] = "CCTL";
|
syntax[base + CTLBACKQ + CTLQUOTE] = "CCTL";
|
||||||
|
syntax[base + CTLARI] = "CCTL";
|
||||||
|
syntax[base + CTLENDARI] = "CCTL";
|
||||||
|
syntax[base + CTLQUOTEMARK] = "CCTL";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -260,8 +298,8 @@ init() {
|
||||||
* Add entries to the syntax table.
|
* Add entries to the syntax table.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
add(p, type)
|
static void
|
||||||
char *p, *type;
|
add(char *p, char *type)
|
||||||
{
|
{
|
||||||
while (*p)
|
while (*p)
|
||||||
syntax[*p++ + base] = type;
|
syntax[*p++ + base] = type;
|
||||||
|
@ -273,8 +311,8 @@ add(p, type)
|
||||||
* Output the syntax table.
|
* Output the syntax table.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
print(name)
|
static void
|
||||||
char *name;
|
print(char *name)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
int col;
|
int col;
|
||||||
|
@ -306,16 +344,18 @@ print(name)
|
||||||
* contiguous, we can test for them quickly.
|
* contiguous, we can test for them quickly.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
char *macro[] = {
|
static char *macro[] = {
|
||||||
"#define is_digit(c)\t((is_type+SYNBASE)[c] & ISDIGIT)",
|
"#define is_digit(c)\t((is_type+SYNBASE)[c] & ISDIGIT)",
|
||||||
"#define is_alpha(c)\t((is_type+SYNBASE)[c] & (ISUPPER|ISLOWER))",
|
"#define is_alpha(c)\t((c) != PEOF && ((c) < CTLESC || (c) > CTLQUOTEMARK) && isalpha((unsigned char) (c)))",
|
||||||
"#define is_name(c)\t((is_type+SYNBASE)[c] & (ISUPPER|ISLOWER|ISUNDER))",
|
"#define is_name(c)\t((c) != PEOF && ((c) < CTLESC || (c) > CTLQUOTEMARK) && ((c) == '_' || isalpha((unsigned char) (c))))",
|
||||||
"#define is_in_name(c)\t((is_type+SYNBASE)[c] & (ISUPPER|ISLOWER|ISUNDER|ISDIGIT))",
|
"#define is_in_name(c)\t((c) != PEOF && ((c) < CTLESC || (c) > CTLQUOTEMARK) && ((c) == '_' || isalnum((unsigned char) (c))))",
|
||||||
"#define is_special(c)\t((is_type+SYNBASE)[c] & (ISSPECL|ISDIGIT))",
|
"#define is_special(c)\t((is_type+SYNBASE)[c] & (ISSPECL|ISDIGIT))",
|
||||||
NULL
|
NULL
|
||||||
};
|
};
|
||||||
|
|
||||||
output_type_macros() {
|
static void
|
||||||
|
output_type_macros(void)
|
||||||
|
{
|
||||||
char **pp;
|
char **pp;
|
||||||
|
|
||||||
if (digit_contig)
|
if (digit_contig)
|
||||||
|
@ -334,7 +374,9 @@ output_type_macros() {
|
||||||
* Output digit conversion table (if digits are not contiguous).
|
* Output digit conversion table (if digits are not contiguous).
|
||||||
*/
|
*/
|
||||||
|
|
||||||
digit_convert() {
|
static void
|
||||||
|
digit_convert(void)
|
||||||
|
{
|
||||||
int maxdigit;
|
int maxdigit;
|
||||||
static char digit[] = "0123456789";
|
static char digit[] = "0123456789";
|
||||||
char *p;
|
char *p;
|
||||||
|
@ -350,7 +392,11 @@ digit_convert() {
|
||||||
for (p = digit ; *p && *p != i ; p++);
|
for (p = digit ; *p && *p != i ; p++);
|
||||||
if (*p == '\0')
|
if (*p == '\0')
|
||||||
p = digit;
|
p = digit;
|
||||||
fprintf(cfile, " %d,\n", p - digit);
|
fprintf(cfile, " %d,\n", (int)(p - digit));
|
||||||
}
|
}
|
||||||
fputs("};\n", cfile);
|
fputs("};\n", cfile);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* $PchId: mksyntax.c,v 1.7 2006/05/23 12:04:27 philip Exp $
|
||||||
|
*/
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
#!/bin/sh -
|
#!/bin/sh -
|
||||||
#
|
#
|
||||||
# Copyright (c) 1991 The Regents of the University of California.
|
# Copyright (c) 1991, 1993
|
||||||
# All rights reserved.
|
# The Regents of the University of California. All rights reserved.
|
||||||
#
|
#
|
||||||
# This code is derived from software contributed to Berkeley by
|
# This code is derived from software contributed to Berkeley by
|
||||||
# Kenneth Almquist.
|
# Kenneth Almquist.
|
||||||
|
@ -14,10 +14,6 @@
|
||||||
# 2. Redistributions in binary form must reproduce the above copyright
|
# 2. Redistributions in binary form must reproduce the above copyright
|
||||||
# notice, this list of conditions and the following disclaimer in the
|
# notice, this list of conditions and the following disclaimer in the
|
||||||
# documentation and/or other materials provided with the distribution.
|
# documentation and/or other materials provided with the distribution.
|
||||||
# 3. All advertising materials mentioning features or use of this software
|
|
||||||
# must display the following acknowledgement:
|
|
||||||
# This product includes software developed by the University of
|
|
||||||
# California, Berkeley and its contributors.
|
|
||||||
# 4. Neither the name of the University nor the names of its contributors
|
# 4. Neither the name of the University nor the names of its contributors
|
||||||
# may be used to endorse or promote products derived from this software
|
# may be used to endorse or promote products derived from this software
|
||||||
# without specific prior written permission.
|
# without specific prior written permission.
|
||||||
|
@ -34,7 +30,8 @@
|
||||||
# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||||
# SUCH DAMAGE.
|
# SUCH DAMAGE.
|
||||||
#
|
#
|
||||||
# @(#)mktokens 5.1 (Berkeley) 3/7/91
|
# @(#)mktokens 8.1 (Berkeley) 5/31/93
|
||||||
|
# $FreeBSD: src/bin/sh/mktokens,v 1.9 2004/04/06 20:06:51 markm Exp $
|
||||||
|
|
||||||
# All calls to awk removed, because Minix bawk is deficient. (kjb)
|
# All calls to awk removed, because Minix bawk is deficient. (kjb)
|
||||||
|
|
||||||
|
@ -42,7 +39,9 @@
|
||||||
# token marks the end of a list. The third column is the name to print in
|
# token marks the end of a list. The third column is the name to print in
|
||||||
# error messages.
|
# error messages.
|
||||||
|
|
||||||
cat > /tmp/ka$$ <<\!
|
#temp=`/usr/bin/mktemp -t ka`
|
||||||
|
temp=/tmp/mkt$$
|
||||||
|
cat > $temp <<\!
|
||||||
TEOF 1 end of file
|
TEOF 1 end of file
|
||||||
TNL 0 newline
|
TNL 0 newline
|
||||||
TSEMI 0 ";"
|
TSEMI 0 ";"
|
||||||
|
@ -70,16 +69,17 @@ TBEGIN 0 "{"
|
||||||
TEND 1 "}"
|
TEND 1 "}"
|
||||||
TCASE 0 "case"
|
TCASE 0 "case"
|
||||||
TESAC 1 "esac"
|
TESAC 1 "esac"
|
||||||
|
TNOT 0 "!"
|
||||||
!
|
!
|
||||||
nl=`wc -l /tmp/ka$$`
|
nl=`wc -l $temp`
|
||||||
exec > token.def
|
exec > token.h
|
||||||
i=0
|
i=0
|
||||||
while read line
|
while read line
|
||||||
do
|
do
|
||||||
set -$- $line
|
set -$- $line
|
||||||
echo "#define $1 $i"
|
echo "#define $1 $i"
|
||||||
i=`expr $i + 1`
|
i=`expr $i + 1`
|
||||||
done </tmp/ka$$
|
done <$temp
|
||||||
echo '
|
echo '
|
||||||
/* Array indicating which tokens mark the end of a list */
|
/* Array indicating which tokens mark the end of a list */
|
||||||
const char tokendlist[] = {'
|
const char tokendlist[] = {'
|
||||||
|
@ -87,18 +87,18 @@ while read line
|
||||||
do
|
do
|
||||||
set -$- $line
|
set -$- $line
|
||||||
echo " $2,"
|
echo " $2,"
|
||||||
done </tmp/ka$$
|
done <$temp
|
||||||
echo '};
|
echo '};
|
||||||
|
|
||||||
char *const tokname[] = {'
|
const char *const tokname[] = {'
|
||||||
sed -e 's/"/\\"/g' \
|
sed -e 's/"/\\"/g' \
|
||||||
-e 's/[^ ]*[ ][ ]*[^ ]*[ ][ ]*\(.*\)/ "\1",/' \
|
-e 's/[^ ]*[ ][ ]*[^ ]*[ ][ ]*\(.*\)/ "\1",/' \
|
||||||
/tmp/ka$$
|
$temp
|
||||||
echo '};
|
echo '};
|
||||||
'
|
'
|
||||||
i=0
|
i=0
|
||||||
go=
|
go=
|
||||||
sed 's/"//g' /tmp/ka$$ |
|
sed 's/"//g' $temp |
|
||||||
while read line
|
while read line
|
||||||
do
|
do
|
||||||
set -$- $line
|
set -$- $line
|
||||||
|
@ -106,7 +106,7 @@ sed 's/"//g' /tmp/ka$$ |
|
||||||
then
|
then
|
||||||
echo "#define KWDOFFSET $i"
|
echo "#define KWDOFFSET $i"
|
||||||
echo
|
echo
|
||||||
echo "char *const parsekwd[] = {"
|
echo "const char *const parsekwd[] = {"
|
||||||
go=true
|
go=true
|
||||||
fi
|
fi
|
||||||
if [ "$go" ]
|
if [ "$go" ]
|
||||||
|
@ -118,4 +118,7 @@ sed 's/"//g' /tmp/ka$$ |
|
||||||
echo ' 0
|
echo ' 0
|
||||||
};'
|
};'
|
||||||
|
|
||||||
rm /tmp/ka$$
|
rm $temp
|
||||||
|
|
||||||
|
#
|
||||||
|
# $PchId: mktokens,v 1.5 2006/05/22 12:43:35 philip Exp $
|
||||||
|
|
50
commands/ash/myhistedit.h
Normal file
50
commands/ash/myhistedit.h
Normal file
|
@ -0,0 +1,50 @@
|
||||||
|
/*-
|
||||||
|
* Copyright (c) 1993
|
||||||
|
* The Regents of the University of California. All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
* 1. Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* 4. Neither the name of the University nor the names of its contributors
|
||||||
|
* may be used to endorse or promote products derived from this software
|
||||||
|
* without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||||
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||||
|
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
|
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||||
|
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||||
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||||
|
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||||
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||||
|
* SUCH DAMAGE.
|
||||||
|
*
|
||||||
|
* @(#)myhistedit.h 8.2 (Berkeley) 5/4/95
|
||||||
|
* $FreeBSD: src/bin/sh/myhistedit.h,v 1.10 2004/04/06 20:06:51 markm Exp $
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <histedit.h>
|
||||||
|
|
||||||
|
extern History *hist;
|
||||||
|
extern EditLine *el;
|
||||||
|
extern int displayhist;
|
||||||
|
|
||||||
|
void histedit(void);
|
||||||
|
void sethistsize(const char *);
|
||||||
|
int histcmd(int, char **);
|
||||||
|
int bindcmd(int, char **);
|
||||||
|
|
||||||
|
/* From libedit */
|
||||||
|
void re_goto_bottom(EditLine *);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* $PchId: myhistedit.h,v 1.5 2006/03/29 15:55:18 philip Exp $
|
||||||
|
*/
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/*-
|
/*-
|
||||||
* Copyright (c) 1991 The Regents of the University of California.
|
* Copyright (c) 1991, 1993
|
||||||
* All rights reserved.
|
* The Regents of the University of California. All rights reserved.
|
||||||
*
|
*
|
||||||
* This code is derived from software contributed to Berkeley by
|
* This code is derived from software contributed to Berkeley by
|
||||||
* Kenneth Almquist.
|
* Kenneth Almquist.
|
||||||
|
@ -13,10 +13,6 @@
|
||||||
* 2. Redistributions in binary form must reproduce the above copyright
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
* notice, this list of conditions and the following disclaimer in the
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
* documentation and/or other materials provided with the distribution.
|
* documentation and/or other materials provided with the distribution.
|
||||||
* 3. All advertising materials mentioning features or use of this software
|
|
||||||
* must display the following acknowledgement:
|
|
||||||
* This product includes software developed by the University of
|
|
||||||
* California, Berkeley and its contributors.
|
|
||||||
* 4. Neither the name of the University nor the names of its contributors
|
* 4. Neither the name of the University nor the names of its contributors
|
||||||
* may be used to endorse or promote products derived from this software
|
* may be used to endorse or promote products derived from this software
|
||||||
* without specific prior written permission.
|
* without specific prior written permission.
|
||||||
|
@ -35,8 +31,14 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef lint
|
#ifndef lint
|
||||||
static char sccsid[] = "@(#)mystring.c 5.1 (Berkeley) 3/7/91";
|
#if 0
|
||||||
|
static char sccsid[] = "@(#)mystring.c 8.2 (Berkeley) 5/4/95";
|
||||||
|
#endif
|
||||||
#endif /* not lint */
|
#endif /* not lint */
|
||||||
|
/*
|
||||||
|
#include <sys/cdefs.h>
|
||||||
|
__FBSDID("$FreeBSD: src/bin/sh/mystring.c,v 1.13 2004/04/06 20:06:51 markm Exp $");
|
||||||
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* String functions.
|
* String functions.
|
||||||
|
@ -44,12 +46,11 @@ static char sccsid[] = "@(#)mystring.c 5.1 (Berkeley) 3/7/91";
|
||||||
* equal(s1, s2) Return true if strings are equal.
|
* equal(s1, s2) Return true if strings are equal.
|
||||||
* scopy(from, to) Copy a string.
|
* scopy(from, to) Copy a string.
|
||||||
* scopyn(from, to, n) Like scopy, but checks for overflow.
|
* scopyn(from, to, n) Like scopy, but checks for overflow.
|
||||||
* strchr(s, c) Find first occurance of c in s.
|
|
||||||
* bcopy(from, to, n) Copy a block of memory.
|
|
||||||
* number(s) Convert a string of digits to an integer.
|
* number(s) Convert a string of digits to an integer.
|
||||||
* is_number(s) Return true if s is a string of digits.
|
* is_number(s) Return true if s is a string of digits.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
#include "shell.h"
|
#include "shell.h"
|
||||||
#include "syntax.h"
|
#include "syntax.h"
|
||||||
#include "error.h"
|
#include "error.h"
|
||||||
|
@ -58,6 +59,14 @@ static char sccsid[] = "@(#)mystring.c 5.1 (Berkeley) 3/7/91";
|
||||||
|
|
||||||
char nullstr[1]; /* zero length string */
|
char nullstr[1]; /* zero length string */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* equal - #defined in mystring.h
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* scopy - #defined in mystring.h
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* scopyn - copy a string from "from" to "to", truncating the string
|
* scopyn - copy a string from "from" to "to", truncating the string
|
||||||
|
@ -66,10 +75,7 @@ char nullstr[1]; /* zero length string */
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void
|
void
|
||||||
scopyn(from, to, size)
|
scopyn(const char *from, char *to, int size)
|
||||||
register char const *from;
|
|
||||||
register char *to;
|
|
||||||
register int size;
|
|
||||||
{
|
{
|
||||||
|
|
||||||
while (--size > 0) {
|
while (--size > 0) {
|
||||||
|
@ -80,58 +86,12 @@ scopyn(from, to, size)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* strchr - find first occurrence of a character in a string.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef SYS5
|
|
||||||
char *
|
|
||||||
mystrchr(s, charwanted)
|
|
||||||
char const *s;
|
|
||||||
register char charwanted;
|
|
||||||
{
|
|
||||||
register char const *scan;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* The odd placement of the two tests is so NUL is findable.
|
|
||||||
*/
|
|
||||||
for (scan = s ; *scan != charwanted ; ) /* ++ moved down for opt. */
|
|
||||||
if (*scan++ == '\0')
|
|
||||||
return NULL;
|
|
||||||
return (char *)scan;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* bcopy - copy bytes
|
|
||||||
*
|
|
||||||
* This routine was derived from code by Henry Spencer.
|
|
||||||
*/
|
|
||||||
|
|
||||||
void
|
|
||||||
mybcopy(src, dst, length)
|
|
||||||
pointer dst;
|
|
||||||
const pointer src;
|
|
||||||
register int length;
|
|
||||||
{
|
|
||||||
register char *d = dst;
|
|
||||||
register char *s = src;
|
|
||||||
|
|
||||||
while (--length >= 0)
|
|
||||||
*d++ = *s++;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* prefix -- see if pfx is a prefix of string.
|
* prefix -- see if pfx is a prefix of string.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int
|
int
|
||||||
prefix(pfx, string)
|
prefix(const char *pfx, const char *string)
|
||||||
register char const *pfx;
|
|
||||||
register char const *string;
|
|
||||||
{
|
{
|
||||||
while (*pfx) {
|
while (*pfx) {
|
||||||
if (*pfx++ != *string++)
|
if (*pfx++ != *string++)
|
||||||
|
@ -147,12 +107,10 @@ prefix(pfx, string)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int
|
int
|
||||||
number(s)
|
number(const char *s)
|
||||||
const char *s;
|
|
||||||
{
|
{
|
||||||
|
|
||||||
if (! is_number(s))
|
if (! is_number(s))
|
||||||
error2("Illegal number", (char *)s);
|
error("Illegal number: %s", (char *)s);
|
||||||
return atoi(s);
|
return atoi(s);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -163,8 +121,7 @@ number(s)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int
|
int
|
||||||
is_number(p)
|
is_number(const char *p)
|
||||||
register const char *p;
|
|
||||||
{
|
{
|
||||||
do {
|
do {
|
||||||
if (! is_digit(*p))
|
if (! is_digit(*p))
|
||||||
|
@ -172,3 +129,7 @@ is_number(p)
|
||||||
} while (*++p != '\0');
|
} while (*++p != '\0');
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* $PchId: mystring.c,v 1.4 2006/05/22 12:21:53 philip Exp $
|
||||||
|
*/
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/*-
|
/*-
|
||||||
* Copyright (c) 1991 The Regents of the University of California.
|
* Copyright (c) 1991, 1993
|
||||||
* All rights reserved.
|
* The Regents of the University of California. All rights reserved.
|
||||||
*
|
*
|
||||||
* This code is derived from software contributed to Berkeley by
|
* This code is derived from software contributed to Berkeley by
|
||||||
* Kenneth Almquist.
|
* Kenneth Almquist.
|
||||||
|
@ -13,10 +13,6 @@
|
||||||
* 2. Redistributions in binary form must reproduce the above copyright
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
* notice, this list of conditions and the following disclaimer in the
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
* documentation and/or other materials provided with the distribution.
|
* documentation and/or other materials provided with the distribution.
|
||||||
* 3. All advertising materials mentioning features or use of this software
|
|
||||||
* must display the following acknowledgement:
|
|
||||||
* This product includes software developed by the University of
|
|
||||||
* California, Berkeley and its contributors.
|
|
||||||
* 4. Neither the name of the University nor the names of its contributors
|
* 4. Neither the name of the University nor the names of its contributors
|
||||||
* may be used to endorse or promote products derived from this software
|
* may be used to endorse or promote products derived from this software
|
||||||
* without specific prior written permission.
|
* without specific prior written permission.
|
||||||
|
@ -33,39 +29,20 @@
|
||||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||||
* SUCH DAMAGE.
|
* SUCH DAMAGE.
|
||||||
*
|
*
|
||||||
* @(#)mystring.h 5.1 (Berkeley) 3/7/91
|
* @(#)mystring.h 8.2 (Berkeley) 5/4/95
|
||||||
|
* $FreeBSD: src/bin/sh/mystring.h,v 1.8 2004/04/06 20:06:51 markm Exp $
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef SYSV
|
#include <string.h>
|
||||||
#define strchr mystrchr
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef __STDC__
|
|
||||||
void scopyn(const char *, char *, int);
|
void scopyn(const char *, char *, int);
|
||||||
char *strchr(const char *, int);
|
|
||||||
void mybcopy(const pointer, pointer, int);
|
|
||||||
int prefix(const char *, const char *);
|
int prefix(const char *, const char *);
|
||||||
int number(const char *);
|
int number(const char *);
|
||||||
int is_number(const char *);
|
int is_number(const char *);
|
||||||
int strcmp(const char *, const char *); /* from C library */
|
|
||||||
char *strcpy(char *, const char *); /* from C library */
|
|
||||||
int strlen(const char *); /* from C library */
|
|
||||||
char *strcat(char *, const char *); /* from C library */
|
|
||||||
char *strerror(int); /* from C library */
|
|
||||||
#else
|
|
||||||
void scopyn();
|
|
||||||
char *strchr();
|
|
||||||
void mybcopy();
|
|
||||||
int prefix();
|
|
||||||
int number();
|
|
||||||
int is_number();
|
|
||||||
int strcmp();
|
|
||||||
char *strcpy();
|
|
||||||
int strlen();
|
|
||||||
char *strcat();
|
|
||||||
char *strerror();
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define equal(s1, s2) (strcmp(s1, s2) == 0)
|
#define equal(s1, s2) (strcmp(s1, s2) == 0)
|
||||||
#define scopy(s1, s2) ((void)strcpy(s2, s1))
|
#define scopy(s1, s2) ((void)strcpy(s2, s1))
|
||||||
#define bcopy(src, dst, n) mybcopy((pointer)(src), (pointer)(dst), n)
|
|
||||||
|
/*
|
||||||
|
* $PchId: mystring.h,v 1.3 2006/03/29 15:49:08 philip Exp $
|
||||||
|
*/
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/*-
|
/*-
|
||||||
* Copyright (c) 1991 The Regents of the University of California.
|
* Copyright (c) 1991, 1993
|
||||||
* All rights reserved.
|
* The Regents of the University of California. All rights reserved.
|
||||||
*
|
*
|
||||||
* This code is derived from software contributed to Berkeley by
|
* This code is derived from software contributed to Berkeley by
|
||||||
* Kenneth Almquist.
|
* Kenneth Almquist.
|
||||||
|
@ -13,10 +13,6 @@
|
||||||
* 2. Redistributions in binary form must reproduce the above copyright
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
* notice, this list of conditions and the following disclaimer in the
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
* documentation and/or other materials provided with the distribution.
|
* documentation and/or other materials provided with the distribution.
|
||||||
* 3. All advertising materials mentioning features or use of this software
|
|
||||||
* must display the following acknowledgement:
|
|
||||||
* This product includes software developed by the University of
|
|
||||||
* California, Berkeley and its contributors.
|
|
||||||
* 4. Neither the name of the University nor the names of its contributors
|
* 4. Neither the name of the University nor the names of its contributors
|
||||||
* may be used to endorse or promote products derived from this software
|
* may be used to endorse or promote products derived from this software
|
||||||
* without specific prior written permission.
|
* without specific prior written permission.
|
||||||
|
@ -33,9 +29,11 @@
|
||||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||||
* SUCH DAMAGE.
|
* SUCH DAMAGE.
|
||||||
*
|
*
|
||||||
* @(#)nodes.c.pat 5.2 (Berkeley) 3/8/91
|
* @(#)nodes.c.pat 8.2 (Berkeley) 5/4/95
|
||||||
|
* $FreeBSD: src/bin/sh/nodes.c.pat,v 1.15 2004/04/06 20:06:51 markm Exp $
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
/*
|
/*
|
||||||
* Routine for dealing with parsed shell commands.
|
* Routine for dealing with parsed shell commands.
|
||||||
*/
|
*/
|
||||||
|
@ -43,35 +41,26 @@
|
||||||
#include "shell.h"
|
#include "shell.h"
|
||||||
#include "nodes.h"
|
#include "nodes.h"
|
||||||
#include "memalloc.h"
|
#include "memalloc.h"
|
||||||
#include "machdep.h"
|
|
||||||
#include "mystring.h"
|
#include "mystring.h"
|
||||||
|
|
||||||
|
#ifndef __minix
|
||||||
int funcblocksize; /* size of structures in function */
|
#include <sys/param.h>
|
||||||
int funcstringsize; /* size of strings in node */
|
|
||||||
#ifdef __STDC__
|
|
||||||
pointer funcblock; /* block to allocate function from */
|
|
||||||
#else
|
|
||||||
char *funcblock; /* block to allocate function from */
|
|
||||||
#endif
|
#endif
|
||||||
char *funcstring; /* block to allocate strings from */
|
#include "machdep.h"
|
||||||
|
|
||||||
|
STATIC int funcblocksize; /* size of structures in function */
|
||||||
|
STATIC int funcstringsize; /* size of strings in node */
|
||||||
|
STATIC pointer funcblock; /* block to allocate function from */
|
||||||
|
STATIC char *funcstring; /* block to allocate strings from */
|
||||||
|
|
||||||
%SIZES
|
%SIZES
|
||||||
|
|
||||||
|
|
||||||
#ifdef __STDC__
|
|
||||||
STATIC void calcsize(union node *);
|
STATIC void calcsize(union node *);
|
||||||
STATIC void sizenodelist(struct nodelist *);
|
STATIC void sizenodelist(struct nodelist *);
|
||||||
STATIC union node *copynode(union node *);
|
STATIC union node *copynode(union node *);
|
||||||
STATIC struct nodelist *copynodelist(struct nodelist *);
|
STATIC struct nodelist *copynodelist(struct nodelist *);
|
||||||
STATIC char *nodesavestr(char *);
|
STATIC char *nodesavestr(char *);
|
||||||
#else
|
|
||||||
STATIC void calcsize();
|
|
||||||
STATIC void sizenodelist();
|
|
||||||
STATIC union node *copynode();
|
|
||||||
STATIC struct nodelist *copynodelist();
|
|
||||||
STATIC char *nodesavestr();
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -80,8 +69,7 @@ STATIC char *nodesavestr();
|
||||||
*/
|
*/
|
||||||
|
|
||||||
union node *
|
union node *
|
||||||
copyfunc(n)
|
copyfunc(union node *n)
|
||||||
union node *n;
|
|
||||||
{
|
{
|
||||||
if (n == NULL)
|
if (n == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
@ -96,8 +84,7 @@ copyfunc(n)
|
||||||
|
|
||||||
|
|
||||||
STATIC void
|
STATIC void
|
||||||
calcsize(n)
|
calcsize(union node *n)
|
||||||
union node *n;
|
|
||||||
{
|
{
|
||||||
%CALCSIZE
|
%CALCSIZE
|
||||||
}
|
}
|
||||||
|
@ -105,8 +92,7 @@ calcsize(n)
|
||||||
|
|
||||||
|
|
||||||
STATIC void
|
STATIC void
|
||||||
sizenodelist(lp)
|
sizenodelist(struct nodelist *lp)
|
||||||
struct nodelist *lp;
|
|
||||||
{
|
{
|
||||||
while (lp) {
|
while (lp) {
|
||||||
funcblocksize += ALIGN(sizeof(struct nodelist));
|
funcblocksize += ALIGN(sizeof(struct nodelist));
|
||||||
|
@ -118,8 +104,7 @@ sizenodelist(lp)
|
||||||
|
|
||||||
|
|
||||||
STATIC union node *
|
STATIC union node *
|
||||||
copynode(n)
|
copynode(union node *n)
|
||||||
union node *n;
|
|
||||||
{
|
{
|
||||||
union node *new;
|
union node *new;
|
||||||
|
|
||||||
|
@ -129,8 +114,7 @@ copynode(n)
|
||||||
|
|
||||||
|
|
||||||
STATIC struct nodelist *
|
STATIC struct nodelist *
|
||||||
copynodelist(lp)
|
copynodelist(struct nodelist *lp)
|
||||||
struct nodelist *lp;
|
|
||||||
{
|
{
|
||||||
struct nodelist *start;
|
struct nodelist *start;
|
||||||
struct nodelist **lpp;
|
struct nodelist **lpp;
|
||||||
|
@ -138,7 +122,7 @@ copynodelist(lp)
|
||||||
lpp = &start;
|
lpp = &start;
|
||||||
while (lp) {
|
while (lp) {
|
||||||
*lpp = funcblock;
|
*lpp = funcblock;
|
||||||
*(char **)&funcblock += ALIGN(sizeof (struct nodelist));
|
funcblock = (char *)funcblock + ALIGN(sizeof(struct nodelist));
|
||||||
(*lpp)->n = copynode(lp->n);
|
(*lpp)->n = copynode(lp->n);
|
||||||
lp = lp->next;
|
lp = lp->next;
|
||||||
lpp = &(*lpp)->next;
|
lpp = &(*lpp)->next;
|
||||||
|
@ -150,14 +134,14 @@ copynodelist(lp)
|
||||||
|
|
||||||
|
|
||||||
STATIC char *
|
STATIC char *
|
||||||
nodesavestr(s)
|
nodesavestr(char *s)
|
||||||
char *s;
|
|
||||||
{
|
{
|
||||||
register char *p = s;
|
char *p = s;
|
||||||
register char *q = funcstring;
|
char *q = funcstring;
|
||||||
char *rtn = funcstring;
|
char *rtn = funcstring;
|
||||||
|
|
||||||
while (*q++ = *p++);
|
while ((*q++ = *p++) != '\0')
|
||||||
|
continue;
|
||||||
funcstring = q;
|
funcstring = q;
|
||||||
return rtn;
|
return rtn;
|
||||||
}
|
}
|
||||||
|
@ -169,9 +153,12 @@ nodesavestr(s)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void
|
void
|
||||||
freefunc(n)
|
freefunc(union node *n)
|
||||||
union node *n;
|
|
||||||
{
|
{
|
||||||
if (n)
|
if (n)
|
||||||
ckfree(n);
|
ckfree(n);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* $PchId: nodes.c.pat,v 1.5 2006/05/22 12:43:57 philip Exp $
|
||||||
|
*/
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
#!/bin/sh -
|
|
||||||
#
|
#
|
||||||
# Copyright (c) 1991 The Regents of the University of California.
|
# Copyright (c) 1991, 1993
|
||||||
# All rights reserved.
|
# The Regents of the University of California. All rights reserved.
|
||||||
#
|
#
|
||||||
# This code is derived from software contributed to Berkeley by
|
# This code is derived from software contributed to Berkeley by
|
||||||
# Kenneth Almquist.
|
# Kenneth Almquist.
|
||||||
|
@ -14,10 +13,6 @@
|
||||||
# 2. Redistributions in binary form must reproduce the above copyright
|
# 2. Redistributions in binary form must reproduce the above copyright
|
||||||
# notice, this list of conditions and the following disclaimer in the
|
# notice, this list of conditions and the following disclaimer in the
|
||||||
# documentation and/or other materials provided with the distribution.
|
# documentation and/or other materials provided with the distribution.
|
||||||
# 3. All advertising materials mentioning features or use of this software
|
|
||||||
# must display the following acknowledgement:
|
|
||||||
# This product includes software developed by the University of
|
|
||||||
# California, Berkeley and its contributors.
|
|
||||||
# 4. Neither the name of the University nor the names of its contributors
|
# 4. Neither the name of the University nor the names of its contributors
|
||||||
# may be used to endorse or promote products derived from this software
|
# may be used to endorse or promote products derived from this software
|
||||||
# without specific prior written permission.
|
# without specific prior written permission.
|
||||||
|
@ -34,7 +29,8 @@
|
||||||
# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||||
# SUCH DAMAGE.
|
# SUCH DAMAGE.
|
||||||
#
|
#
|
||||||
# @(#)nodetypes 5.1 (Berkeley) 3/7/91
|
# @(#)nodetypes 8.2 (Berkeley) 5/4/95
|
||||||
|
# $FreeBSD: src/bin/sh/nodetypes,v 1.9 2004/04/06 20:06:51 markm Exp $
|
||||||
|
|
||||||
# This file describes the nodes used in parse trees. Unindented lines
|
# This file describes the nodes used in parse trees. Unindented lines
|
||||||
# contain a node type followed by a structure tag. Subsequent indented
|
# contain a node type followed by a structure tag. Subsequent indented
|
||||||
|
@ -118,7 +114,9 @@ NARG narg # represents a word
|
||||||
|
|
||||||
NTO nfile # fd> fname
|
NTO nfile # fd> fname
|
||||||
NFROM nfile # fd< fname
|
NFROM nfile # fd< fname
|
||||||
|
NFROMTO nfile # fd<> fname
|
||||||
NAPPEND nfile # fd>> fname
|
NAPPEND nfile # fd>> fname
|
||||||
|
NCLOBBER nfile # fd>| fname
|
||||||
type int
|
type int
|
||||||
next nodeptr # next redirection in list
|
next nodeptr # next redirection in list
|
||||||
fd int # file descriptor being redirected
|
fd int # file descriptor being redirected
|
||||||
|
@ -131,6 +129,8 @@ NFROMFD ndup # fd>&dupfd
|
||||||
next nodeptr # next redirection in list
|
next nodeptr # next redirection in list
|
||||||
fd int # file descriptor being redirected
|
fd int # file descriptor being redirected
|
||||||
dupfd int # file descriptor to duplicate
|
dupfd int # file descriptor to duplicate
|
||||||
|
vname nodeptr # file name if fd>&$var
|
||||||
|
|
||||||
|
|
||||||
NHERE nhere # fd<<\!
|
NHERE nhere # fd<<\!
|
||||||
NXHERE nhere # fd<<!
|
NXHERE nhere # fd<<!
|
||||||
|
@ -138,3 +138,10 @@ NXHERE nhere # fd<<!
|
||||||
next nodeptr # next redirection in list
|
next nodeptr # next redirection in list
|
||||||
fd int # file descriptor being redirected
|
fd int # file descriptor being redirected
|
||||||
doc nodeptr # input to command (NARG node)
|
doc nodeptr # input to command (NARG node)
|
||||||
|
|
||||||
|
NNOT nnot # ! command (actually pipeline)
|
||||||
|
type int
|
||||||
|
com nodeptr
|
||||||
|
|
||||||
|
#
|
||||||
|
# $PchId: nodetypes,v 1.3 2006/03/29 15:43:35 philip Exp $
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/*-
|
/*-
|
||||||
* Copyright (c) 1991 The Regents of the University of California.
|
* Copyright (c) 1991, 1993
|
||||||
* All rights reserved.
|
* The Regents of the University of California. All rights reserved.
|
||||||
*
|
*
|
||||||
* This code is derived from software contributed to Berkeley by
|
* This code is derived from software contributed to Berkeley by
|
||||||
* Kenneth Almquist.
|
* Kenneth Almquist.
|
||||||
|
@ -13,10 +13,6 @@
|
||||||
* 2. Redistributions in binary form must reproduce the above copyright
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
* notice, this list of conditions and the following disclaimer in the
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
* documentation and/or other materials provided with the distribution.
|
* documentation and/or other materials provided with the distribution.
|
||||||
* 3. All advertising materials mentioning features or use of this software
|
|
||||||
* must display the following acknowledgement:
|
|
||||||
* This product includes software developed by the University of
|
|
||||||
* California, Berkeley and its contributors.
|
|
||||||
* 4. Neither the name of the University nor the names of its contributors
|
* 4. Neither the name of the University nor the names of its contributors
|
||||||
* may be used to endorse or promote products derived from this software
|
* may be used to endorse or promote products derived from this software
|
||||||
* without specific prior written permission.
|
* without specific prior written permission.
|
||||||
|
@ -35,8 +31,18 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef lint
|
#ifndef lint
|
||||||
static char sccsid[] = "@(#)options.c 5.2 (Berkeley) 3/13/91";
|
#if 0
|
||||||
|
static char sccsid[] = "@(#)options.c 8.2 (Berkeley) 5/4/95";
|
||||||
|
#endif
|
||||||
#endif /* not lint */
|
#endif /* not lint */
|
||||||
|
/*
|
||||||
|
#include <sys/cdefs.h>
|
||||||
|
__FBSDID("$FreeBSD: src/bin/sh/options.c,v 1.21 2004/04/06 20:06:51 markm Exp $");
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <signal.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
#include "shell.h"
|
#include "shell.h"
|
||||||
#define DEFINE_OPTIONS
|
#define DEFINE_OPTIONS
|
||||||
|
@ -52,25 +58,24 @@ static char sccsid[] = "@(#)options.c 5.2 (Berkeley) 3/13/91";
|
||||||
#include "memalloc.h"
|
#include "memalloc.h"
|
||||||
#include "error.h"
|
#include "error.h"
|
||||||
#include "mystring.h"
|
#include "mystring.h"
|
||||||
|
#include "builtins.h"
|
||||||
|
#if !defined(NO_HISTORY) && !defined(EDITLINE)
|
||||||
|
#include "myhistedit.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
char *arg0; /* value of $0 */
|
char *arg0; /* value of $0 */
|
||||||
struct shparam shellparam; /* current positional parameters */
|
struct shparam shellparam; /* current positional parameters */
|
||||||
char **argptr; /* argument list for builtin commands */
|
char **argptr; /* argument list for builtin commands */
|
||||||
char *optarg; /* set by nextopt (like getopt) */
|
char *shoptarg; /* set by nextopt (like getopt) */
|
||||||
char *optptr; /* used by nextopt */
|
char *optptr; /* used by nextopt */
|
||||||
int editable; /* isatty(0) && isatty(1) */
|
|
||||||
|
|
||||||
char *minusc; /* argument to -c option */
|
char *minusc; /* argument to -c option */
|
||||||
|
|
||||||
|
|
||||||
#ifdef __STDC__
|
|
||||||
STATIC void options(int);
|
STATIC void options(int);
|
||||||
|
STATIC void minus_o(char *, int);
|
||||||
STATIC void setoption(int, int);
|
STATIC void setoption(int, int);
|
||||||
#else
|
STATIC int getopts(char *, char *, char **, char ***, char **);
|
||||||
STATIC void options();
|
|
||||||
STATIC void setoption();
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -78,46 +83,55 @@ STATIC void setoption();
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void
|
void
|
||||||
procargs(argc, argv)
|
procargs(int argc, char **argv)
|
||||||
char **argv;
|
|
||||||
{
|
{
|
||||||
char *p;
|
int i;
|
||||||
|
|
||||||
argptr = argv;
|
argptr = argv;
|
||||||
if (argc > 0)
|
if (argc > 0)
|
||||||
argptr++;
|
argptr++;
|
||||||
for (p = optval ; p < optval + sizeof optval - 1 ; p++)
|
for (i = 0; i < NOPTS; i++)
|
||||||
*p = 2;
|
optlist[i].val = 2;
|
||||||
|
privileged = (getuid() != geteuid() || getgid() != getegid());
|
||||||
options(1);
|
options(1);
|
||||||
if (*argptr == NULL && minusc == NULL)
|
if (*argptr == NULL && minusc == NULL)
|
||||||
sflag = 1;
|
sflag = 1;
|
||||||
editable = (isatty(0) && isatty(1));
|
if (iflag == 2 && sflag == 1 && isatty(0) && isatty(1))
|
||||||
if (iflag == 2 && sflag == 1 && editable)
|
|
||||||
iflag = 1;
|
iflag = 1;
|
||||||
if (jflag == 2)
|
if (mflag == 2)
|
||||||
jflag = iflag;
|
mflag = iflag;
|
||||||
for (p = optval ; p < optval + sizeof optval - 1 ; p++)
|
for (i = 0; i < NOPTS; i++)
|
||||||
if (*p == 2)
|
if (optlist[i].val == 2)
|
||||||
*p = 0;
|
optlist[i].val = 0;
|
||||||
arg0 = argv[0];
|
arg0 = argv[0];
|
||||||
if (sflag == 0) {
|
if (sflag == 0 && minusc == NULL) {
|
||||||
arg0 = *argptr++;
|
commandname = arg0 = *argptr++;
|
||||||
if (minusc == NULL) {
|
|
||||||
commandname = arg0;
|
|
||||||
setinputfile(commandname, 0);
|
setinputfile(commandname, 0);
|
||||||
}
|
}
|
||||||
}
|
/* POSIX 1003.2: first arg after -c cmd is $0, remainder $1... */
|
||||||
|
if (argptr && minusc && *argptr)
|
||||||
|
arg0 = *argptr++;
|
||||||
|
|
||||||
shellparam.p = argptr;
|
shellparam.p = argptr;
|
||||||
|
shellparam.reset = 1;
|
||||||
/* assert(shellparam.malloc == 0 && shellparam.nparam == 0); */
|
/* assert(shellparam.malloc == 0 && shellparam.nparam == 0); */
|
||||||
while (*argptr) {
|
while (*argptr) {
|
||||||
shellparam.nparam++;
|
shellparam.nparam++;
|
||||||
argptr++;
|
argptr++;
|
||||||
}
|
}
|
||||||
setinteractive(iflag);
|
optschanged();
|
||||||
setjobctl(jflag);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
optschanged(void)
|
||||||
|
{
|
||||||
|
setinteractive(iflag);
|
||||||
|
#if !defined(NO_HISTORY) && !defined(EDITLINE)
|
||||||
|
histedit();
|
||||||
|
#endif
|
||||||
|
setjobctl(mflag);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Process shell options. The global variable argptr contains a pointer
|
* Process shell options. The global variable argptr contains a pointer
|
||||||
|
@ -125,8 +139,9 @@ procargs(argc, argv)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
STATIC void
|
STATIC void
|
||||||
options(cmdline) {
|
options(int cmdline)
|
||||||
register char *p;
|
{
|
||||||
|
char *p;
|
||||||
int val;
|
int val;
|
||||||
int c;
|
int c;
|
||||||
|
|
||||||
|
@ -136,7 +151,7 @@ options(cmdline) {
|
||||||
argptr++;
|
argptr++;
|
||||||
if ((c = *p++) == '-') {
|
if ((c = *p++) == '-') {
|
||||||
val = 1;
|
val = 1;
|
||||||
if (p[0] == '\0' || p[0] == '-' && p[1] == '\0') {
|
if (p[0] == '\0' || (p[0] == '-' && p[1] == '\0')) {
|
||||||
if (!cmdline) {
|
if (!cmdline) {
|
||||||
/* "-" means turn off -x and -v */
|
/* "-" means turn off -x and -v */
|
||||||
if (p[0] == '\0')
|
if (p[0] == '\0')
|
||||||
|
@ -166,26 +181,79 @@ options(cmdline) {
|
||||||
#ifdef NOHACK
|
#ifdef NOHACK
|
||||||
break;
|
break;
|
||||||
#endif
|
#endif
|
||||||
|
} else if (c == 'o') {
|
||||||
|
minus_o(*argptr, val);
|
||||||
|
if (*argptr)
|
||||||
|
argptr++;
|
||||||
} else {
|
} else {
|
||||||
|
if (c == 'p' && !val && privileged) {
|
||||||
|
(void) setuid(getuid());
|
||||||
|
(void) setgid(getgid());
|
||||||
|
}
|
||||||
setoption(c, val);
|
setoption(c, val);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (! cmdline)
|
}
|
||||||
break;
|
}
|
||||||
|
|
||||||
|
STATIC void
|
||||||
|
minus_o(char *name, int val)
|
||||||
|
{
|
||||||
|
int doneset, i;
|
||||||
|
|
||||||
|
if (name == NULL) {
|
||||||
|
if (val) {
|
||||||
|
/* "Pretty" output. */
|
||||||
|
out1str("Current option settings\n");
|
||||||
|
for (i = 0; i < NOPTS; i++)
|
||||||
|
out1fmt("%-16s%s\n", optlist[i].name,
|
||||||
|
optlist[i].val ? "on" : "off");
|
||||||
|
} else {
|
||||||
|
/* Output suitable for re-input to shell. */
|
||||||
|
for (doneset = i = 0; i < NOPTS; i++)
|
||||||
|
if (optlist[i].val) {
|
||||||
|
if (!doneset) {
|
||||||
|
out1str("set");
|
||||||
|
doneset = 1;
|
||||||
|
}
|
||||||
|
out1fmt(" -o %s", optlist[i].name);
|
||||||
|
}
|
||||||
|
if (doneset)
|
||||||
|
out1c('\n');
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
for (i = 0; i < NOPTS; i++)
|
||||||
|
if (equal(name, optlist[i].name)) {
|
||||||
|
if (!val && privileged && equal(name, "privileged")) {
|
||||||
|
(void) setuid(getuid());
|
||||||
|
(void) setgid(getgid());
|
||||||
|
}
|
||||||
|
setoption(optlist[i].letter, val);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
error("Illegal option -o %s", name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
STATIC void
|
STATIC void
|
||||||
setoption(flag, val)
|
setoption(int flag, int val)
|
||||||
char flag;
|
|
||||||
int val;
|
|
||||||
{
|
{
|
||||||
register char *p;
|
int i;
|
||||||
|
|
||||||
if ((p = strchr(optchar, flag)) == NULL)
|
for (i = 0; i < NOPTS; i++)
|
||||||
|
if (optlist[i].letter == flag) {
|
||||||
|
optlist[i].val = val;
|
||||||
|
if (val) {
|
||||||
|
/* #%$ hack for ksh semantics */
|
||||||
|
if (flag == 'V')
|
||||||
|
Eflag = 0;
|
||||||
|
else if (flag == 'E')
|
||||||
|
Vflag = 0;
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
error("Illegal option -%c", flag);
|
error("Illegal option -%c", flag);
|
||||||
optval[p - optchar] = val;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -194,10 +262,12 @@ setoption(flag, val)
|
||||||
INCLUDE "options.h"
|
INCLUDE "options.h"
|
||||||
|
|
||||||
SHELLPROC {
|
SHELLPROC {
|
||||||
char *p;
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < NOPTS; i++)
|
||||||
|
optlist[i].val = 0;
|
||||||
|
optschanged();
|
||||||
|
|
||||||
for (p = optval ; p < optval + sizeof optval ; p++)
|
|
||||||
*p = 0;
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -207,8 +277,7 @@ SHELLPROC {
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void
|
void
|
||||||
setparam(argv)
|
setparam(char **argv)
|
||||||
char **argv;
|
|
||||||
{
|
{
|
||||||
char **newparam;
|
char **newparam;
|
||||||
char **ap;
|
char **ap;
|
||||||
|
@ -233,8 +302,7 @@ setparam(argv)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void
|
void
|
||||||
freeparam(param)
|
freeparam(struct shparam *param)
|
||||||
struct shparam *param;
|
|
||||||
{
|
{
|
||||||
char **ap;
|
char **ap;
|
||||||
|
|
||||||
|
@ -251,7 +319,9 @@ freeparam(param)
|
||||||
* The shift builtin command.
|
* The shift builtin command.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
shiftcmd(argc, argv) char **argv; {
|
int
|
||||||
|
shiftcmd(int argc, char **argv)
|
||||||
|
{
|
||||||
int n;
|
int n;
|
||||||
char **ap1, **ap2;
|
char **ap1, **ap2;
|
||||||
|
|
||||||
|
@ -259,7 +329,7 @@ shiftcmd(argc, argv) char **argv; {
|
||||||
if (argc > 1)
|
if (argc > 1)
|
||||||
n = number(argv[1]);
|
n = number(argv[1]);
|
||||||
if (n > shellparam.nparam)
|
if (n > shellparam.nparam)
|
||||||
n = shellparam.nparam;
|
error("can't shift that many");
|
||||||
INTOFF;
|
INTOFF;
|
||||||
shellparam.nparam -= n;
|
shellparam.nparam -= n;
|
||||||
for (ap1 = shellparam.p ; --n >= 0 ; ap1++) {
|
for (ap1 = shellparam.p ; --n >= 0 ; ap1++) {
|
||||||
|
@ -279,13 +349,14 @@ shiftcmd(argc, argv) char **argv; {
|
||||||
* The set command builtin.
|
* The set command builtin.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
setcmd(argc, argv) char **argv; {
|
int
|
||||||
|
setcmd(int argc, char **argv)
|
||||||
|
{
|
||||||
if (argc == 1)
|
if (argc == 1)
|
||||||
return showvarscmd(argc, argv);
|
return showvarscmd(argc, argv);
|
||||||
INTOFF;
|
INTOFF;
|
||||||
options(0);
|
options(0);
|
||||||
setinteractive(iflag);
|
optschanged();
|
||||||
setjobctl(jflag);
|
|
||||||
if (*argptr != NULL) {
|
if (*argptr != NULL) {
|
||||||
setparam(argptr);
|
setparam(argptr);
|
||||||
}
|
}
|
||||||
|
@ -294,6 +365,15 @@ setcmd(argc, argv) char **argv; {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
getoptsreset(const char *value)
|
||||||
|
{
|
||||||
|
if (number(value) == 1) {
|
||||||
|
shellparam.optnext = NULL;
|
||||||
|
shellparam.reset = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The getopts builtin. Shellparam.optnext points to the next argument
|
* The getopts builtin. Shellparam.optnext points to the next argument
|
||||||
* to be processed. Shellparam.optptr points to the next character to
|
* to be processed. Shellparam.optptr points to the next character to
|
||||||
|
@ -301,63 +381,127 @@ setcmd(argc, argv) char **argv; {
|
||||||
* then it's the first time getopts has been called.
|
* then it's the first time getopts has been called.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
getoptscmd(argc, argv) char **argv; {
|
int
|
||||||
register char *p, *q;
|
getoptscmd(int argc, char **argv)
|
||||||
char c;
|
{
|
||||||
|
char **optbase = NULL;
|
||||||
|
|
||||||
|
if (argc < 3)
|
||||||
|
error("usage: getopts optstring var [arg]");
|
||||||
|
else if (argc == 3)
|
||||||
|
optbase = shellparam.p;
|
||||||
|
else
|
||||||
|
optbase = &argv[3];
|
||||||
|
|
||||||
|
if (shellparam.reset == 1) {
|
||||||
|
shellparam.optnext = optbase;
|
||||||
|
shellparam.optptr = NULL;
|
||||||
|
shellparam.reset = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return getopts(argv[1], argv[2], optbase, &shellparam.optnext,
|
||||||
|
&shellparam.optptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
STATIC int
|
||||||
|
getopts(char *optstr, char *optvar, char **optfirst, char ***optnext,
|
||||||
|
char **optptr)
|
||||||
|
{
|
||||||
|
char *p, *q;
|
||||||
|
char c = '?';
|
||||||
|
int done = 0;
|
||||||
|
int ind = 0;
|
||||||
|
int err = 0;
|
||||||
char s[10];
|
char s[10];
|
||||||
|
|
||||||
if (argc != 3)
|
if ((p = *optptr) == NULL || *p == '\0') {
|
||||||
error("Usage: getopts optstring var");
|
/* Current word is done, advance */
|
||||||
if (shellparam.optnext == NULL) {
|
if (*optnext == NULL)
|
||||||
shellparam.optnext = shellparam.p;
|
return 1;
|
||||||
shellparam.optptr = NULL;
|
p = **optnext;
|
||||||
}
|
|
||||||
if ((p = shellparam.optptr) == NULL || *p == '\0') {
|
|
||||||
p = *shellparam.optnext;
|
|
||||||
if (p == NULL || *p != '-' || *++p == '\0') {
|
if (p == NULL || *p != '-' || *++p == '\0') {
|
||||||
atend:
|
atend:
|
||||||
fmtstr(s, 10, "%d", shellparam.optnext - shellparam.p + 1);
|
ind = *optnext - optfirst + 1;
|
||||||
setvar("OPTIND", s, 0);
|
*optnext = NULL;
|
||||||
shellparam.optnext = NULL;
|
p = NULL;
|
||||||
return 1;
|
done = 1;
|
||||||
|
goto out;
|
||||||
}
|
}
|
||||||
shellparam.optnext++;
|
(*optnext)++;
|
||||||
if (p[0] == '-' && p[1] == '\0') /* check for "--" */
|
if (p[0] == '-' && p[1] == '\0') /* check for "--" */
|
||||||
goto atend;
|
goto atend;
|
||||||
}
|
}
|
||||||
|
|
||||||
c = *p++;
|
c = *p++;
|
||||||
for (q = argv[1] ; *q != c ; ) {
|
for (q = optstr; *q != c; ) {
|
||||||
if (*q == '\0') {
|
if (*q == '\0') {
|
||||||
|
if (optstr[0] == ':') {
|
||||||
|
s[0] = c;
|
||||||
|
s[1] = '\0';
|
||||||
|
err |= setvarsafe("OPTARG", s, 0);
|
||||||
|
}
|
||||||
|
else {
|
||||||
out1fmt("Illegal option -%c\n", c);
|
out1fmt("Illegal option -%c\n", c);
|
||||||
|
(void) unsetvar("OPTARG");
|
||||||
|
}
|
||||||
c = '?';
|
c = '?';
|
||||||
goto out;
|
goto bad;
|
||||||
}
|
}
|
||||||
if (*++q == ':')
|
if (*++q == ':')
|
||||||
q++;
|
q++;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (*++q == ':') {
|
if (*++q == ':') {
|
||||||
if (*p == '\0') {
|
if (*p == '\0' && (p = **optnext) == NULL) {
|
||||||
if ((p = *shellparam.optnext) == NULL) {
|
if (optstr[0] == ':') {
|
||||||
out1fmt("No arg for -%c option\n", c);
|
|
||||||
c = '?';
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
shellparam.optnext++;
|
|
||||||
}
|
|
||||||
setvar("OPTARG", p, 0);
|
|
||||||
p = "";
|
|
||||||
}
|
|
||||||
out:
|
|
||||||
shellparam.optptr = p;
|
|
||||||
s[0] = c;
|
s[0] = c;
|
||||||
s[1] = '\0';
|
s[1] = '\0';
|
||||||
setvar(argv[2], s, 0);
|
err |= setvarsafe("OPTARG", s, 0);
|
||||||
fmtstr(s, 10, "%d", shellparam.optnext - shellparam.p + 1);
|
c = ':';
|
||||||
setvar("OPTIND", s, 0);
|
}
|
||||||
return 0;
|
else {
|
||||||
|
out1fmt("No arg for -%c option\n", c);
|
||||||
|
(void) unsetvar("OPTARG");
|
||||||
|
c = '?';
|
||||||
|
}
|
||||||
|
goto bad;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (p == **optnext)
|
||||||
|
(*optnext)++;
|
||||||
|
setvarsafe("OPTARG", p, 0);
|
||||||
|
p = NULL;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
setvarsafe("OPTARG", "", 0);
|
||||||
|
ind = *optnext - optfirst + 1;
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
bad:
|
||||||
|
ind = 1;
|
||||||
|
*optnext = NULL;
|
||||||
|
p = NULL;
|
||||||
|
out:
|
||||||
|
*optptr = p;
|
||||||
|
fmtstr(s, sizeof(s), "%d", ind);
|
||||||
|
err |= setvarsafe("OPTIND", s, VNOFUNC);
|
||||||
|
s[0] = c;
|
||||||
|
s[1] = '\0';
|
||||||
|
err |= setvarsafe(optvar, s, 0);
|
||||||
|
if (err) {
|
||||||
|
*optnext = NULL;
|
||||||
|
*optptr = NULL;
|
||||||
|
flushall();
|
||||||
|
exraise(EXERROR);
|
||||||
|
}
|
||||||
|
return done;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
* XXX - should get rid of. have all builtins use getopt(3). the
|
||||||
|
* library getopt must have the BSD extension static variable "optreset"
|
||||||
|
* otherwise it can't be used within the shell safely.
|
||||||
|
*
|
||||||
* Standard option processing (a la getopt) for builtin routines. The
|
* Standard option processing (a la getopt) for builtin routines. The
|
||||||
* only argument that is passed to nextopt is the option string; the
|
* only argument that is passed to nextopt is the option string; the
|
||||||
* other arguments are unnecessary. It return the character, or '\0' on
|
* other arguments are unnecessary. It return the character, or '\0' on
|
||||||
|
@ -365,10 +509,9 @@ out:
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int
|
int
|
||||||
nextopt(optstring)
|
nextopt(char *optstring)
|
||||||
char *optstring;
|
|
||||||
{
|
{
|
||||||
register char *p, *q;
|
char *p, *q;
|
||||||
char c;
|
char c;
|
||||||
|
|
||||||
if ((p = optptr) == NULL || *p == '\0') {
|
if ((p = optptr) == NULL || *p == '\0') {
|
||||||
|
@ -389,9 +532,13 @@ nextopt(optstring)
|
||||||
if (*++q == ':') {
|
if (*++q == ':') {
|
||||||
if (*p == '\0' && (p = *argptr++) == NULL)
|
if (*p == '\0' && (p = *argptr++) == NULL)
|
||||||
error("No arg for -%c option", c);
|
error("No arg for -%c option", c);
|
||||||
optarg = p;
|
shoptarg = p;
|
||||||
p = NULL;
|
p = NULL;
|
||||||
}
|
}
|
||||||
optptr = p;
|
optptr = p;
|
||||||
return c;
|
return c;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* $PchId: options.c,v 1.5 2006/05/22 12:23:10 philip Exp $
|
||||||
|
*/
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/*-
|
/*-
|
||||||
* Copyright (c) 1991 The Regents of the University of California.
|
* Copyright (c) 1991, 1993
|
||||||
* All rights reserved.
|
* The Regents of the University of California. All rights reserved.
|
||||||
*
|
*
|
||||||
* This code is derived from software contributed to Berkeley by
|
* This code is derived from software contributed to Berkeley by
|
||||||
* Kenneth Almquist.
|
* Kenneth Almquist.
|
||||||
|
@ -13,10 +13,6 @@
|
||||||
* 2. Redistributions in binary form must reproduce the above copyright
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
* notice, this list of conditions and the following disclaimer in the
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
* documentation and/or other materials provided with the distribution.
|
* documentation and/or other materials provided with the distribution.
|
||||||
* 3. All advertising materials mentioning features or use of this software
|
|
||||||
* must display the following acknowledgement:
|
|
||||||
* This product includes software developed by the University of
|
|
||||||
* California, Berkeley and its contributors.
|
|
||||||
* 4. Neither the name of the University nor the names of its contributors
|
* 4. Neither the name of the University nor the names of its contributors
|
||||||
* may be used to endorse or promote products derived from this software
|
* may be used to endorse or promote products derived from this software
|
||||||
* without specific prior written permission.
|
* without specific prior written permission.
|
||||||
|
@ -33,12 +29,14 @@
|
||||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||||
* SUCH DAMAGE.
|
* SUCH DAMAGE.
|
||||||
*
|
*
|
||||||
* @(#)options.h 5.1 (Berkeley) 3/7/91
|
* @(#)options.h 8.2 (Berkeley) 5/4/95
|
||||||
|
* $FreeBSD: src/bin/sh/options.h,v 1.13 2004/04/06 20:06:51 markm Exp $
|
||||||
*/
|
*/
|
||||||
|
|
||||||
struct shparam {
|
struct shparam {
|
||||||
int nparam; /* number of positional parameters (without $0) */
|
int nparam; /* # of positional parameters (without $0) */
|
||||||
char malloc; /* true if parameter list dynamicly allocated */
|
unsigned char malloc; /* if parameter list dynamically allocated */
|
||||||
|
unsigned char reset; /* if getopts has been reset */
|
||||||
char **p; /* parameter list */
|
char **p; /* parameter list */
|
||||||
char **optnext; /* next parameter to be processed by getopts */
|
char **optnext; /* next parameter to be processed by getopts */
|
||||||
char *optptr; /* used by getopts */
|
char *optptr; /* used by getopts */
|
||||||
|
@ -46,25 +44,56 @@ struct shparam {
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#define eflag optval[0]
|
#define eflag optlist[0].val
|
||||||
#define fflag optval[1]
|
#define fflag optlist[1].val
|
||||||
#define Iflag optval[2]
|
#define Iflag optlist[2].val
|
||||||
#define iflag optval[3]
|
#define iflag optlist[3].val
|
||||||
#define jflag optval[4]
|
#define mflag optlist[4].val
|
||||||
#define nflag optval[5]
|
#define nflag optlist[5].val
|
||||||
#define sflag optval[6]
|
#define sflag optlist[6].val
|
||||||
#define xflag optval[7]
|
#define xflag optlist[7].val
|
||||||
#define zflag optval[8]
|
#define vflag optlist[8].val
|
||||||
#define vflag optval[9]
|
#define Vflag optlist[9].val
|
||||||
|
#define Eflag optlist[10].val
|
||||||
|
#define Cflag optlist[11].val
|
||||||
|
#define aflag optlist[12].val
|
||||||
|
#define bflag optlist[13].val
|
||||||
|
#define uflag optlist[14].val
|
||||||
|
#define privileged optlist[15].val
|
||||||
|
#define Tflag optlist[16].val
|
||||||
|
#define Pflag optlist[17].val
|
||||||
|
|
||||||
#define NOPTS 10
|
#define NOPTS 18
|
||||||
|
|
||||||
|
struct optent {
|
||||||
|
const char *name;
|
||||||
|
const char letter;
|
||||||
|
char val;
|
||||||
|
};
|
||||||
|
|
||||||
#ifdef DEFINE_OPTIONS
|
#ifdef DEFINE_OPTIONS
|
||||||
const char optchar[NOPTS+1] = "efIijnsxzv"; /* shell flags */
|
struct optent optlist[NOPTS] = {
|
||||||
char optval[NOPTS+1]; /* values of option flags */
|
{ "errexit", 'e', 0 },
|
||||||
|
{ "noglob", 'f', 0 },
|
||||||
|
{ "ignoreeof", 'I', 0 },
|
||||||
|
{ "interactive",'i', 0 },
|
||||||
|
{ "monitor", 'm', 0 },
|
||||||
|
{ "noexec", 'n', 0 },
|
||||||
|
{ "stdin", 's', 0 },
|
||||||
|
{ "xtrace", 'x', 0 },
|
||||||
|
{ "verbose", 'v', 0 },
|
||||||
|
{ "vi", 'V', 0 },
|
||||||
|
{ "emacs", 'E', 0 },
|
||||||
|
{ "noclobber", 'C', 0 },
|
||||||
|
{ "allexport", 'a', 0 },
|
||||||
|
{ "notify", 'b', 0 },
|
||||||
|
{ "nounset", 'u', 0 },
|
||||||
|
{ "privileged", 'p', 0 },
|
||||||
|
{ "trapsasync", 'T', 0 },
|
||||||
|
{ "physical", 'P', 0 },
|
||||||
|
};
|
||||||
#else
|
#else
|
||||||
extern const char optchar[NOPTS+1];
|
extern struct optent optlist[NOPTS];
|
||||||
extern char optval[NOPTS+1];
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
@ -72,19 +101,19 @@ extern char *minusc; /* argument to -c option */
|
||||||
extern char *arg0; /* $0 */
|
extern char *arg0; /* $0 */
|
||||||
extern struct shparam shellparam; /* $@ */
|
extern struct shparam shellparam; /* $@ */
|
||||||
extern char **argptr; /* argument list for builtin commands */
|
extern char **argptr; /* argument list for builtin commands */
|
||||||
extern char *optarg; /* set by nextopt */
|
extern char *shoptarg; /* set by nextopt */
|
||||||
extern char *optptr; /* used by nextopt */
|
extern char *optptr; /* used by nextopt */
|
||||||
extern int editable; /* isatty(0) && isatty(1) */
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef __STDC__
|
|
||||||
void procargs(int, char **);
|
void procargs(int, char **);
|
||||||
|
void optschanged(void);
|
||||||
void setparam(char **);
|
void setparam(char **);
|
||||||
void freeparam(struct shparam *);
|
void freeparam(struct shparam *);
|
||||||
|
int shiftcmd(int, char **);
|
||||||
|
int setcmd(int, char **);
|
||||||
|
int getoptscmd(int, char **);
|
||||||
int nextopt(char *);
|
int nextopt(char *);
|
||||||
#else
|
void getoptsreset(const char *);
|
||||||
void procargs();
|
|
||||||
void setparam();
|
/*
|
||||||
void freeparam();
|
* $PchId: options.h,v 1.4 2006/03/29 15:37:43 philip Exp $
|
||||||
int nextopt();
|
*/
|
||||||
#endif
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/*-
|
/*-
|
||||||
* Copyright (c) 1991 The Regents of the University of California.
|
* Copyright (c) 1991, 1993
|
||||||
* All rights reserved.
|
* The Regents of the University of California. All rights reserved.
|
||||||
*
|
*
|
||||||
* This code is derived from software contributed to Berkeley by
|
* This code is derived from software contributed to Berkeley by
|
||||||
* Kenneth Almquist.
|
* Kenneth Almquist.
|
||||||
|
@ -13,10 +13,6 @@
|
||||||
* 2. Redistributions in binary form must reproduce the above copyright
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
* notice, this list of conditions and the following disclaimer in the
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
* documentation and/or other materials provided with the distribution.
|
* documentation and/or other materials provided with the distribution.
|
||||||
* 3. All advertising materials mentioning features or use of this software
|
|
||||||
* must display the following acknowledgement:
|
|
||||||
* This product includes software developed by the University of
|
|
||||||
* California, Berkeley and its contributors.
|
|
||||||
* 4. Neither the name of the University nor the names of its contributors
|
* 4. Neither the name of the University nor the names of its contributors
|
||||||
* may be used to endorse or promote products derived from this software
|
* may be used to endorse or promote products derived from this software
|
||||||
* without specific prior written permission.
|
* without specific prior written permission.
|
||||||
|
@ -35,7 +31,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef lint
|
#ifndef lint
|
||||||
static char sccsid[] = "@(#)output.c 5.1 (Berkeley) 3/7/91";
|
static char sccsid[] = "@(#)output.c 8.1 (Berkeley) 5/31/93";
|
||||||
#endif /* not lint */
|
#endif /* not lint */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -55,12 +51,16 @@ static char sccsid[] = "@(#)output.c 5.1 (Berkeley) 3/7/91";
|
||||||
#include "output.h"
|
#include "output.h"
|
||||||
#include "memalloc.h"
|
#include "memalloc.h"
|
||||||
#include "error.h"
|
#include "error.h"
|
||||||
|
#include "var.h"
|
||||||
#ifdef __STDC__
|
#ifdef __STDC__
|
||||||
#include "stdarg.h"
|
#include "stdarg.h"
|
||||||
#else
|
#else
|
||||||
#include <varargs.h>
|
#include <varargs.h>
|
||||||
#endif
|
#endif
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
|
||||||
#define OUTBUFSIZ BUFSIZ
|
#define OUTBUFSIZ BUFSIZ
|
||||||
|
@ -115,15 +115,20 @@ open_mem(block, length, file)
|
||||||
|
|
||||||
void
|
void
|
||||||
out1str(p)
|
out1str(p)
|
||||||
char *p;
|
const char *p;
|
||||||
{
|
{
|
||||||
outstr(p, out1);
|
outstr(p, out1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
out1qstr(const char *p)
|
||||||
|
{
|
||||||
|
outqstr(p, out1);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
out2str(p)
|
out2str(const char *p)
|
||||||
char *p;
|
|
||||||
{
|
{
|
||||||
outstr(p, out2);
|
outstr(p, out2);
|
||||||
}
|
}
|
||||||
|
@ -131,11 +136,42 @@ out2str(p)
|
||||||
|
|
||||||
void
|
void
|
||||||
outstr(p, file)
|
outstr(p, file)
|
||||||
register char *p;
|
register const char *p;
|
||||||
register struct output *file;
|
register struct output *file;
|
||||||
{
|
{
|
||||||
while (*p)
|
while (*p)
|
||||||
outc(*p++, file);
|
outc(*p++, file);
|
||||||
|
if (file == out2)
|
||||||
|
flushout(file);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Like outstr(), but quote for re-input into the shell. */
|
||||||
|
void
|
||||||
|
outqstr(const char *p, struct output *file)
|
||||||
|
{
|
||||||
|
char ch;
|
||||||
|
|
||||||
|
if (p[strcspn(p, "|&;<>()$`\\\"'")] == '\0' && (!ifsset() ||
|
||||||
|
p[strcspn(p, ifsval())] == '\0')) {
|
||||||
|
outstr(p, file);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
out1c('\'');
|
||||||
|
while ((ch = *p++) != '\0') {
|
||||||
|
switch (ch) {
|
||||||
|
case '\'':
|
||||||
|
/*
|
||||||
|
* Can't quote single quotes inside single quotes;
|
||||||
|
* close them, write escaped single quote, open again.
|
||||||
|
*/
|
||||||
|
outstr("'\\''", file);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
outc(ch, file);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
out1c('\'');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -208,7 +244,8 @@ freestdout() {
|
||||||
|
|
||||||
#ifdef __STDC__
|
#ifdef __STDC__
|
||||||
void
|
void
|
||||||
outfmt(struct output *file, char *fmt, ...) {
|
outfmt(struct output *file, const char *fmt, ...)
|
||||||
|
{
|
||||||
va_list ap;
|
va_list ap;
|
||||||
|
|
||||||
va_start(ap, fmt);
|
va_start(ap, fmt);
|
||||||
|
@ -218,7 +255,8 @@ outfmt(struct output *file, char *fmt, ...) {
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
out1fmt(char *fmt, ...) {
|
out1fmt(const char *fmt, ...)
|
||||||
|
{
|
||||||
va_list ap;
|
va_list ap;
|
||||||
|
|
||||||
va_start(ap, fmt);
|
va_start(ap, fmt);
|
||||||
|
@ -226,9 +264,20 @@ out1fmt(char *fmt, ...) {
|
||||||
va_end(ap);
|
va_end(ap);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
dprintf(const char *fmt, ...)
|
||||||
|
{
|
||||||
|
va_list ap;
|
||||||
|
|
||||||
|
va_start(ap, fmt);
|
||||||
|
doformat(out2, fmt, ap);
|
||||||
|
va_end(ap);
|
||||||
|
flushout(out2);
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
fmtstr(char *outbuf, int length, char *fmt, ...) {
|
fmtstr(char *outbuf, int length, const char *fmt, ...)
|
||||||
|
{
|
||||||
va_list ap;
|
va_list ap;
|
||||||
struct output strout;
|
struct output strout;
|
||||||
|
|
||||||
|
@ -275,6 +324,19 @@ out1fmt(va_alist)
|
||||||
va_end(ap);
|
va_end(ap);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
dprintf(va_alist)
|
||||||
|
va_dcl
|
||||||
|
{
|
||||||
|
va_list ap;
|
||||||
|
char *fmt;
|
||||||
|
|
||||||
|
va_start(ap);
|
||||||
|
fmt = va_arg(ap, char *);
|
||||||
|
doformat(out2, fmt, ap);
|
||||||
|
va_end(ap);
|
||||||
|
flushout(out2);
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
fmtstr(va_alist)
|
fmtstr(va_alist)
|
||||||
|
@ -325,10 +387,7 @@ static const char digit[17] = "0123456789ABCDEF";
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
doformat(dest, f, ap)
|
doformat(struct output *dest, const char *f, va_list ap)
|
||||||
register struct output *dest;
|
|
||||||
register char *f; /* format string */
|
|
||||||
va_list ap;
|
|
||||||
{
|
{
|
||||||
register char c;
|
register char c;
|
||||||
char temp[TEMPSIZE];
|
char temp[TEMPSIZE];
|
||||||
|
@ -517,15 +576,6 @@ xwrite(fd, buf, nbytes)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Version of ioctl that retries after a signal is caught.
|
* $PchId: output.c,v 1.6 2006/05/22 12:46:03 philip Exp $
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int
|
|
||||||
xioctl(fd, request, arg) {
|
|
||||||
int i;
|
|
||||||
|
|
||||||
while ((i = ioctl(fd, request, arg)) == -1 && errno == EINTR);
|
|
||||||
return i;
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/*-
|
/*-
|
||||||
* Copyright (c) 1991 The Regents of the University of California.
|
* Copyright (c) 1991, 1993
|
||||||
* All rights reserved.
|
* The Regents of the University of California. All rights reserved.
|
||||||
*
|
*
|
||||||
* This code is derived from software contributed to Berkeley by
|
* This code is derived from software contributed to Berkeley by
|
||||||
* Kenneth Almquist.
|
* Kenneth Almquist.
|
||||||
|
@ -13,10 +13,6 @@
|
||||||
* 2. Redistributions in binary form must reproduce the above copyright
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
* notice, this list of conditions and the following disclaimer in the
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
* documentation and/or other materials provided with the distribution.
|
* documentation and/or other materials provided with the distribution.
|
||||||
* 3. All advertising materials mentioning features or use of this software
|
|
||||||
* must display the following acknowledgement:
|
|
||||||
* This product includes software developed by the University of
|
|
||||||
* California, Berkeley and its contributors.
|
|
||||||
* 4. Neither the name of the University nor the names of its contributors
|
* 4. Neither the name of the University nor the names of its contributors
|
||||||
* may be used to endorse or promote products derived from this software
|
* may be used to endorse or promote products derived from this software
|
||||||
* without specific prior written permission.
|
* without specific prior written permission.
|
||||||
|
@ -33,11 +29,14 @@
|
||||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||||
* SUCH DAMAGE.
|
* SUCH DAMAGE.
|
||||||
*
|
*
|
||||||
* @(#)output.h 5.1 (Berkeley) 3/7/91
|
* @(#)output.h 8.2 (Berkeley) 5/4/95
|
||||||
|
* $FreeBSD: src/bin/sh/output.h,v 1.13 2004/04/06 20:06:51 markm Exp $
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef OUTPUT_INCL
|
#ifndef OUTPUT_INCL
|
||||||
|
|
||||||
|
#include <stdarg.h>
|
||||||
|
|
||||||
struct output {
|
struct output {
|
||||||
char *nextc;
|
char *nextc;
|
||||||
int nleft;
|
int nleft;
|
||||||
|
@ -53,38 +52,27 @@ extern struct output memout;
|
||||||
extern struct output *out1;
|
extern struct output *out1;
|
||||||
extern struct output *out2;
|
extern struct output *out2;
|
||||||
|
|
||||||
|
#ifndef __printflike
|
||||||
|
#define __printflike(a,b)
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef __STDC__
|
void open_mem(char *, int, struct output *);
|
||||||
void outstr(char *, struct output *);
|
void out1str(const char *);
|
||||||
void out1str(char *);
|
void out1qstr(const char *);
|
||||||
void out2str(char *);
|
void out2str(const char *);
|
||||||
void outfmt(struct output *, char *, ...);
|
void out2qstr(const char *);
|
||||||
void out1fmt(char *, ...);
|
void outstr(const char *, struct output *);
|
||||||
void fmtstr(char *, int, char *, ...);
|
void outqstr(const char *, struct output *);
|
||||||
/* void doformat(struct output *, char *, va_list); */
|
|
||||||
void doformat();
|
|
||||||
void emptyoutbuf(struct output *);
|
void emptyoutbuf(struct output *);
|
||||||
void flushall(void);
|
void flushall(void);
|
||||||
void flushout(struct output *);
|
void flushout(struct output *);
|
||||||
void freestdout(void);
|
void freestdout(void);
|
||||||
|
void outfmt(struct output *, const char *, ...) __printflike(2, 3);
|
||||||
|
void out1fmt(const char *, ...) __printflike(1, 2);
|
||||||
|
void dprintf(const char *, ...) __printflike(1, 2);
|
||||||
|
void fmtstr(char *, int, const char *, ...) __printflike(3, 4);
|
||||||
|
void doformat(struct output *, const char *, va_list) __printflike(2, 0);
|
||||||
int xwrite(int, char *, int);
|
int xwrite(int, char *, int);
|
||||||
int xioctl(int, int, int);
|
|
||||||
#else
|
|
||||||
void outstr();
|
|
||||||
void out1str();
|
|
||||||
void out2str();
|
|
||||||
void outfmt();
|
|
||||||
void out1fmt();
|
|
||||||
void fmtstr();
|
|
||||||
/* void doformat(); */
|
|
||||||
void doformat();
|
|
||||||
void emptyoutbuf();
|
|
||||||
void flushall();
|
|
||||||
void flushout();
|
|
||||||
void freestdout();
|
|
||||||
int xwrite();
|
|
||||||
int xioctl();
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define outc(c, file) (--(file)->nleft < 0? (emptyoutbuf(file), *(file)->nextc++ = (c)) : (*(file)->nextc++ = (c)))
|
#define outc(c, file) (--(file)->nleft < 0? (emptyoutbuf(file), *(file)->nextc++ = (c)) : (*(file)->nextc++ = (c)))
|
||||||
#define out1c(c) outc(c, out1);
|
#define out1c(c) outc(c, out1);
|
||||||
|
@ -92,3 +80,7 @@ int xioctl();
|
||||||
|
|
||||||
#define OUTPUT_INCL
|
#define OUTPUT_INCL
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
* $PchId: output.h,v 1.5 2006/05/23 12:04:54 philip Exp $
|
||||||
|
*/
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -1,6 +1,6 @@
|
||||||
/*-
|
/*-
|
||||||
* Copyright (c) 1991 The Regents of the University of California.
|
* Copyright (c) 1991, 1993
|
||||||
* All rights reserved.
|
* The Regents of the University of California. All rights reserved.
|
||||||
*
|
*
|
||||||
* This code is derived from software contributed to Berkeley by
|
* This code is derived from software contributed to Berkeley by
|
||||||
* Kenneth Almquist.
|
* Kenneth Almquist.
|
||||||
|
@ -13,10 +13,6 @@
|
||||||
* 2. Redistributions in binary form must reproduce the above copyright
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
* notice, this list of conditions and the following disclaimer in the
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
* documentation and/or other materials provided with the distribution.
|
* documentation and/or other materials provided with the distribution.
|
||||||
* 3. All advertising materials mentioning features or use of this software
|
|
||||||
* must display the following acknowledgement:
|
|
||||||
* This product includes software developed by the University of
|
|
||||||
* California, Berkeley and its contributors.
|
|
||||||
* 4. Neither the name of the University nor the names of its contributors
|
* 4. Neither the name of the University nor the names of its contributors
|
||||||
* may be used to endorse or promote products derived from this software
|
* may be used to endorse or promote products derived from this software
|
||||||
* without specific prior written permission.
|
* without specific prior written permission.
|
||||||
|
@ -33,7 +29,8 @@
|
||||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||||
* SUCH DAMAGE.
|
* SUCH DAMAGE.
|
||||||
*
|
*
|
||||||
* @(#)parser.h 5.1 (Berkeley) 3/7/91
|
* @(#)parser.h 8.3 (Berkeley) 5/4/95
|
||||||
|
* $FreeBSD: src/bin/sh/parser.h,v 1.10 2004/04/06 20:06:51 markm Exp $
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* control characters in argument strings */
|
/* control characters in argument strings */
|
||||||
|
@ -42,18 +39,27 @@
|
||||||
#define CTLENDVAR '\203'
|
#define CTLENDVAR '\203'
|
||||||
#define CTLBACKQ '\204'
|
#define CTLBACKQ '\204'
|
||||||
#define CTLQUOTE 01 /* ored with CTLBACKQ code if in quotes */
|
#define CTLQUOTE 01 /* ored with CTLBACKQ code if in quotes */
|
||||||
|
/* CTLBACKQ | CTLQUOTE == '\205' */
|
||||||
|
#define CTLARI '\206'
|
||||||
|
#define CTLENDARI '\207'
|
||||||
|
#define CTLQUOTEMARK '\210'
|
||||||
|
|
||||||
/* variable substitution byte (follows CTLVAR) */
|
/* variable substitution byte (follows CTLVAR) */
|
||||||
#define VSTYPE 07 /* type of variable substitution */
|
#define VSTYPE 0x0f /* type of variable substitution */
|
||||||
#define VSNUL 040 /* colon--treat the empty string as unset */
|
#define VSNUL 0x10 /* colon--treat the empty string as unset */
|
||||||
#define VSQUOTE 0100 /* inside double quotes--suppress splitting */
|
#define VSQUOTE 0x80 /* inside double quotes--suppress splitting */
|
||||||
|
|
||||||
/* values of VSTYPE field */
|
/* values of VSTYPE field */
|
||||||
#define VSNORMAL 1 /* normal variable: $var or ${var} */
|
#define VSNORMAL 0x1 /* normal variable: $var or ${var} */
|
||||||
#define VSMINUS 2 /* ${var-text} */
|
#define VSMINUS 0x2 /* ${var-text} */
|
||||||
#define VSPLUS 3 /* ${var+text} */
|
#define VSPLUS 0x3 /* ${var+text} */
|
||||||
#define VSQUESTION 4 /* ${var?message} */
|
#define VSQUESTION 0x4 /* ${var?message} */
|
||||||
#define VSASSIGN 5 /* ${var=text} */
|
#define VSASSIGN 0x5 /* ${var=text} */
|
||||||
|
#define VSTRIMLEFT 0x6 /* ${var#pattern} */
|
||||||
|
#define VSTRIMLEFTMAX 0x7 /* ${var##pattern} */
|
||||||
|
#define VSTRIMRIGHT 0x8 /* ${var%pattern} */
|
||||||
|
#define VSTRIMRIGHTMAX 0x9 /* ${var%%pattern} */
|
||||||
|
#define VSLENGTH 0xa /* ${#var} */
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -63,12 +69,14 @@
|
||||||
*/
|
*/
|
||||||
extern int tokpushback;
|
extern int tokpushback;
|
||||||
#define NEOF ((union node *)&tokpushback)
|
#define NEOF ((union node *)&tokpushback)
|
||||||
|
extern int whichprompt; /* 1 == PS1, 2 == PS2 */
|
||||||
|
|
||||||
|
|
||||||
#ifdef __STDC__
|
|
||||||
union node *parsecmd(int);
|
union node *parsecmd(int);
|
||||||
|
void fixredir(union node *, const char *, int);
|
||||||
int goodname(char *);
|
int goodname(char *);
|
||||||
#else
|
char *getprompt(void *);
|
||||||
union node *parsecmd();
|
|
||||||
int goodname();
|
/*
|
||||||
#endif
|
* $PchId: parser.h,v 1.3 2006/03/29 14:33:35 philip Exp $
|
||||||
|
*/
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/*-
|
/*-
|
||||||
* Copyright (c) 1991 The Regents of the University of California.
|
* Copyright (c) 1991, 1993
|
||||||
* All rights reserved.
|
* The Regents of the University of California. All rights reserved.
|
||||||
*
|
*
|
||||||
* This code is derived from software contributed to Berkeley by
|
* This code is derived from software contributed to Berkeley by
|
||||||
* Kenneth Almquist.
|
* Kenneth Almquist.
|
||||||
|
@ -13,10 +13,6 @@
|
||||||
* 2. Redistributions in binary form must reproduce the above copyright
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
* notice, this list of conditions and the following disclaimer in the
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
* documentation and/or other materials provided with the distribution.
|
* documentation and/or other materials provided with the distribution.
|
||||||
* 3. All advertising materials mentioning features or use of this software
|
|
||||||
* must display the following acknowledgement:
|
|
||||||
* This product includes software developed by the University of
|
|
||||||
* California, Berkeley and its contributors.
|
|
||||||
* 4. Neither the name of the University nor the names of its contributors
|
* 4. Neither the name of the University nor the names of its contributors
|
||||||
* may be used to endorse or promote products derived from this software
|
* may be used to endorse or promote products derived from this software
|
||||||
* without specific prior written permission.
|
* without specific prior written permission.
|
||||||
|
@ -35,8 +31,23 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef lint
|
#ifndef lint
|
||||||
static char sccsid[] = "@(#)redir.c 5.1 (Berkeley) 3/7/91";
|
#if 0
|
||||||
|
static char sccsid[] = "@(#)redir.c 8.2 (Berkeley) 5/4/95";
|
||||||
|
#endif
|
||||||
#endif /* not lint */
|
#endif /* not lint */
|
||||||
|
/*
|
||||||
|
#include <sys/cdefs.h>
|
||||||
|
__FBSDID("$FreeBSD: src/bin/sh/redir.c,v 1.26 2004/04/06 20:06:51 markm Exp $");
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <signal.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Code for dealing with input/output redirection.
|
* Code for dealing with input/output redirection.
|
||||||
|
@ -47,15 +58,10 @@ static char sccsid[] = "@(#)redir.c 5.1 (Berkeley) 3/7/91";
|
||||||
#include "jobs.h"
|
#include "jobs.h"
|
||||||
#include "expand.h"
|
#include "expand.h"
|
||||||
#include "redir.h"
|
#include "redir.h"
|
||||||
#include "eval.h"
|
|
||||||
#include "output.h"
|
#include "output.h"
|
||||||
#include "memalloc.h"
|
#include "memalloc.h"
|
||||||
#include "error.h"
|
#include "error.h"
|
||||||
#include <sys/types.h>
|
#include "options.h"
|
||||||
#include <signal.h>
|
|
||||||
#include <fcntl.h>
|
|
||||||
#include <errno.h>
|
|
||||||
#include <limits.h>
|
|
||||||
|
|
||||||
|
|
||||||
#define EMPTY -2 /* marks an unused slot in redirtab */
|
#define EMPTY -2 /* marks an unused slot in redirtab */
|
||||||
|
@ -65,25 +71,21 @@ static char sccsid[] = "@(#)redir.c 5.1 (Berkeley) 3/7/91";
|
||||||
MKINIT
|
MKINIT
|
||||||
struct redirtab {
|
struct redirtab {
|
||||||
struct redirtab *next;
|
struct redirtab *next;
|
||||||
short renamed[10];
|
int renamed[10];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
MKINIT struct redirtab *redirlist;
|
MKINIT struct redirtab *redirlist;
|
||||||
|
|
||||||
/* We keep track of whether or not fd0 has been redirected. This is for
|
/*
|
||||||
background commands, where we want to redirect fd0 to /dev/null only
|
* We keep track of whether or not fd0 has been redirected. This is for
|
||||||
if it hasn't already been redirected. */
|
* background commands, where we want to redirect fd0 to /dev/null only
|
||||||
int fd0_redirected = 0;
|
* if it hasn't already been redirected.
|
||||||
|
*/
|
||||||
|
STATIC int fd0_redirected = 0;
|
||||||
|
|
||||||
#ifdef __STDC__
|
STATIC void openredirect(union node *, char[10 ]);
|
||||||
STATIC void openredirect(union node *, char *);
|
|
||||||
STATIC int openhere(union node *);
|
STATIC int openhere(union node *);
|
||||||
#else
|
|
||||||
STATIC void openredirect();
|
|
||||||
STATIC int openhere();
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -95,14 +97,13 @@ STATIC int openhere();
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void
|
void
|
||||||
redirect(redir, flags)
|
redirect(union node *redir, int flags)
|
||||||
union node *redir;
|
|
||||||
int flags;
|
|
||||||
{
|
{
|
||||||
union node *n;
|
union node *n;
|
||||||
struct redirtab *sv;
|
struct redirtab *sv = NULL;
|
||||||
int i;
|
int i;
|
||||||
int fd;
|
int fd;
|
||||||
|
int try;
|
||||||
char memory[10]; /* file descriptors to write to memory */
|
char memory[10]; /* file descriptors to write to memory */
|
||||||
|
|
||||||
for (i = 10 ; --i >= 0 ; )
|
for (i = 10 ; --i >= 0 ; )
|
||||||
|
@ -117,20 +118,37 @@ redirect(redir, flags)
|
||||||
}
|
}
|
||||||
for (n = redir ; n ; n = n->nfile.next) {
|
for (n = redir ; n ; n = n->nfile.next) {
|
||||||
fd = n->nfile.fd;
|
fd = n->nfile.fd;
|
||||||
|
try = 0;
|
||||||
|
if ((n->nfile.type == NTOFD || n->nfile.type == NFROMFD) &&
|
||||||
|
n->ndup.dupfd == fd)
|
||||||
|
continue; /* redirect from/to same file descriptor */
|
||||||
|
|
||||||
if ((flags & REDIR_PUSH) && sv->renamed[fd] == EMPTY) {
|
if ((flags & REDIR_PUSH) && sv->renamed[fd] == EMPTY) {
|
||||||
INTOFF;
|
INTOFF;
|
||||||
if ((i = copyfd(fd, 10)) != EMPTY) {
|
again:
|
||||||
|
if ((i = fcntl(fd, F_DUPFD, 10)) == -1) {
|
||||||
|
switch (errno) {
|
||||||
|
case EBADF:
|
||||||
|
if (!try) {
|
||||||
|
openredirect(n, memory);
|
||||||
|
try++;
|
||||||
|
goto again;
|
||||||
|
}
|
||||||
|
/* FALLTHROUGH*/
|
||||||
|
default:
|
||||||
|
INTON;
|
||||||
|
error("%d: %s", fd, strerror(errno));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!try) {
|
||||||
sv->renamed[fd] = i;
|
sv->renamed[fd] = i;
|
||||||
close(fd);
|
|
||||||
}
|
}
|
||||||
INTON;
|
INTON;
|
||||||
if (i == EMPTY)
|
|
||||||
error("Out of file descriptors");
|
|
||||||
} else {
|
|
||||||
close(fd);
|
|
||||||
}
|
}
|
||||||
if (fd == 0)
|
if (fd == 0)
|
||||||
fd0_redirected++;
|
fd0_redirected++;
|
||||||
|
if (!try)
|
||||||
openredirect(n, memory);
|
openredirect(n, memory);
|
||||||
}
|
}
|
||||||
if (memory[1])
|
if (memory[1])
|
||||||
|
@ -141,16 +159,15 @@ redirect(redir, flags)
|
||||||
|
|
||||||
|
|
||||||
STATIC void
|
STATIC void
|
||||||
openredirect(redir, memory)
|
openredirect(union node *redir, char memory[10])
|
||||||
union node *redir;
|
|
||||||
char memory[10];
|
|
||||||
{
|
{
|
||||||
|
struct stat sb;
|
||||||
int fd = redir->nfile.fd;
|
int fd = redir->nfile.fd;
|
||||||
char *fname;
|
char *fname;
|
||||||
int f;
|
int f;
|
||||||
|
|
||||||
/* Assume redirection succeeds. */
|
/* Assume redirection succeeds. */
|
||||||
exitstatus = 0;
|
{ extern int exitstatus; exitstatus = 0; }
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* We suppress interrupts so that we won't leave open file
|
* We suppress interrupts so that we won't leave open file
|
||||||
|
@ -163,34 +180,35 @@ openredirect(redir, memory)
|
||||||
case NFROM:
|
case NFROM:
|
||||||
fname = redir->nfile.expfname;
|
fname = redir->nfile.expfname;
|
||||||
if ((f = open(fname, O_RDONLY)) < 0)
|
if ((f = open(fname, O_RDONLY)) < 0)
|
||||||
error("cannot open %s: %s", fname, errmsg(errno, E_OPEN));
|
error("cannot open %s: %s", fname, strerror(errno));
|
||||||
movefd:
|
movefd:
|
||||||
if (f != fd) {
|
if (f != fd) {
|
||||||
copyfd(f, fd);
|
dup2(f, fd);
|
||||||
close(f);
|
close(f);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case NFROMTO:
|
||||||
|
fname = redir->nfile.expfname;
|
||||||
|
if ((f = open(fname, O_RDWR|O_CREAT, 0666)) < 0)
|
||||||
|
error("cannot create %s: %s", fname, strerror(errno));
|
||||||
|
goto movefd;
|
||||||
case NTO:
|
case NTO:
|
||||||
fname = redir->nfile.expfname;
|
fname = redir->nfile.expfname;
|
||||||
#ifdef O_CREAT
|
if (Cflag && stat(fname, &sb) != -1 && S_ISREG(sb.st_mode))
|
||||||
|
error("cannot create %s: %s", fname,
|
||||||
|
strerror(EEXIST));
|
||||||
if ((f = open(fname, O_WRONLY|O_CREAT|O_TRUNC, 0666)) < 0)
|
if ((f = open(fname, O_WRONLY|O_CREAT|O_TRUNC, 0666)) < 0)
|
||||||
error("cannot create %s: %s", fname, errmsg(errno, E_CREAT));
|
error("cannot create %s: %s", fname, strerror(errno));
|
||||||
#else
|
goto movefd;
|
||||||
if ((f = creat(fname, 0666)) < 0)
|
case NCLOBBER:
|
||||||
error("cannot create %s: %s", fname, errmsg(errno, E_CREAT));
|
fname = redir->nfile.expfname;
|
||||||
#endif
|
if ((f = open(fname, O_WRONLY|O_CREAT|O_TRUNC, 0666)) < 0)
|
||||||
|
error("cannot create %s: %s", fname, strerror(errno));
|
||||||
goto movefd;
|
goto movefd;
|
||||||
case NAPPEND:
|
case NAPPEND:
|
||||||
fname = redir->nfile.expfname;
|
fname = redir->nfile.expfname;
|
||||||
#ifdef O_APPEND
|
|
||||||
if ((f = open(fname, O_WRONLY|O_CREAT|O_APPEND, 0666)) < 0)
|
if ((f = open(fname, O_WRONLY|O_CREAT|O_APPEND, 0666)) < 0)
|
||||||
error("cannot create %s: %s", fname, errmsg(errno, E_CREAT));
|
error("cannot create %s: %s", fname, strerror(errno));
|
||||||
#else
|
|
||||||
if ((f = open(fname, O_WRONLY)) < 0
|
|
||||||
&& (f = creat(fname, 0666)) < 0)
|
|
||||||
error("cannot create %s: %s", fname, errmsg(errno, E_CREAT));
|
|
||||||
lseek(f, 0L, 2);
|
|
||||||
#endif
|
|
||||||
goto movefd;
|
goto movefd;
|
||||||
case NTOFD:
|
case NTOFD:
|
||||||
case NFROMFD:
|
case NFROMFD:
|
||||||
|
@ -198,7 +216,9 @@ movefd:
|
||||||
if (memory[redir->ndup.dupfd])
|
if (memory[redir->ndup.dupfd])
|
||||||
memory[fd] = 1;
|
memory[fd] = 1;
|
||||||
else
|
else
|
||||||
copyfd(redir->ndup.dupfd, fd);
|
dup2(redir->ndup.dupfd, fd);
|
||||||
|
} else {
|
||||||
|
close(fd);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case NHERE:
|
case NHERE:
|
||||||
|
@ -219,14 +239,13 @@ movefd:
|
||||||
*/
|
*/
|
||||||
|
|
||||||
STATIC int
|
STATIC int
|
||||||
openhere(redir)
|
openhere(union node *redir)
|
||||||
union node *redir;
|
|
||||||
{
|
{
|
||||||
int pip[2];
|
int pip[2];
|
||||||
int len;
|
int len = 0;
|
||||||
|
|
||||||
if (pipe(pip) < 0)
|
if (pipe(pip) < 0)
|
||||||
error("Pipe call failed");
|
error("Pipe call failed: %s", strerror(errno));
|
||||||
if (redir->type == NHERE) {
|
if (redir->type == NHERE) {
|
||||||
len = strlen(redir->nhere.doc->narg.text);
|
len = strlen(redir->nhere.doc->narg.text);
|
||||||
if (len <= PIPESIZE) {
|
if (len <= PIPESIZE) {
|
||||||
|
@ -239,9 +258,7 @@ openhere(redir)
|
||||||
signal(SIGINT, SIG_IGN);
|
signal(SIGINT, SIG_IGN);
|
||||||
signal(SIGQUIT, SIG_IGN);
|
signal(SIGQUIT, SIG_IGN);
|
||||||
signal(SIGHUP, SIG_IGN);
|
signal(SIGHUP, SIG_IGN);
|
||||||
#ifdef SIGTSTP
|
|
||||||
signal(SIGTSTP, SIG_IGN);
|
signal(SIGTSTP, SIG_IGN);
|
||||||
#endif
|
|
||||||
signal(SIGPIPE, SIG_DFL);
|
signal(SIGPIPE, SIG_DFL);
|
||||||
if (redir->type == NHERE)
|
if (redir->type == NHERE)
|
||||||
xwrite(pip[1], redir->nhere.doc->narg.text, len);
|
xwrite(pip[1], redir->nhere.doc->narg.text, len);
|
||||||
|
@ -261,18 +278,20 @@ out:
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void
|
void
|
||||||
popredir() {
|
popredir(void)
|
||||||
register struct redirtab *rp = redirlist;
|
{
|
||||||
|
struct redirtab *rp = redirlist;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
for (i = 0 ; i < 10 ; i++) {
|
for (i = 0 ; i < 10 ; i++) {
|
||||||
if (rp->renamed[i] != EMPTY) {
|
if (rp->renamed[i] != EMPTY) {
|
||||||
if (i == 0)
|
if (i == 0)
|
||||||
fd0_redirected--;
|
fd0_redirected--;
|
||||||
close(i);
|
|
||||||
if (rp->renamed[i] >= 0) {
|
if (rp->renamed[i] >= 0) {
|
||||||
copyfd(rp->renamed[i], i);
|
dup2(rp->renamed[i], i);
|
||||||
close(rp->renamed[i]);
|
close(rp->renamed[i]);
|
||||||
|
} else {
|
||||||
|
close(i);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -282,8 +301,6 @@ popredir() {
|
||||||
INTON;
|
INTON;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Undo all redirections. Called on error or interrupt.
|
* Undo all redirections. Called on error or interrupt.
|
||||||
*/
|
*/
|
||||||
|
@ -303,14 +320,21 @@ SHELLPROC {
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/* Return true if fd 0 has already been redirected at least once. */
|
||||||
|
int
|
||||||
|
fd0_redirected_p(void)
|
||||||
|
{
|
||||||
|
return fd0_redirected != 0;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Discard all saved file descriptors.
|
* Discard all saved file descriptors.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void
|
void
|
||||||
clearredir() {
|
clearredir(void)
|
||||||
register struct redirtab *rp;
|
{
|
||||||
|
struct redirtab *rp;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
for (rp = redirlist ; rp ; rp = rp->next) {
|
for (rp = redirlist ; rp ; rp = rp->next) {
|
||||||
|
@ -323,48 +347,6 @@ clearredir() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copy a file descriptor, like the F_DUPFD option of fcntl. Returns -1
|
* $PchId: redir.c,v 1.5 2006/05/22 12:27:37 philip Exp $
|
||||||
* if the source file descriptor is closed, EMPTY if there are no unused
|
|
||||||
* file descriptors left.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int
|
|
||||||
copyfd(from, to) {
|
|
||||||
#ifdef F_DUPFD
|
|
||||||
int newfd;
|
|
||||||
|
|
||||||
newfd = fcntl(from, F_DUPFD, to);
|
|
||||||
if (newfd < 0 && errno == EMFILE)
|
|
||||||
return EMPTY;
|
|
||||||
return newfd;
|
|
||||||
#else
|
|
||||||
char toclose[32];
|
|
||||||
int i;
|
|
||||||
int newfd;
|
|
||||||
int e;
|
|
||||||
|
|
||||||
for (i = 0 ; i < to ; i++)
|
|
||||||
toclose[i] = 0;
|
|
||||||
INTOFF;
|
|
||||||
while ((newfd = dup(from)) >= 0 && newfd < to)
|
|
||||||
toclose[newfd] = 1;
|
|
||||||
e = errno;
|
|
||||||
for (i = 0 ; i < to ; i++) {
|
|
||||||
if (toclose[i])
|
|
||||||
close(i);
|
|
||||||
}
|
|
||||||
INTON;
|
|
||||||
if (newfd < 0 && e == EMFILE)
|
|
||||||
return EMPTY;
|
|
||||||
return newfd;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Return true if fd 0 has already been redirected at least once. */
|
|
||||||
int
|
|
||||||
fd0_redirected_p () {
|
|
||||||
return fd0_redirected != 0;
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/*-
|
/*-
|
||||||
* Copyright (c) 1991 The Regents of the University of California.
|
* Copyright (c) 1991, 1993
|
||||||
* All rights reserved.
|
* The Regents of the University of California. All rights reserved.
|
||||||
*
|
*
|
||||||
* This code is derived from software contributed to Berkeley by
|
* This code is derived from software contributed to Berkeley by
|
||||||
* Kenneth Almquist.
|
* Kenneth Almquist.
|
||||||
|
@ -13,10 +13,6 @@
|
||||||
* 2. Redistributions in binary form must reproduce the above copyright
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
* notice, this list of conditions and the following disclaimer in the
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
* documentation and/or other materials provided with the distribution.
|
* documentation and/or other materials provided with the distribution.
|
||||||
* 3. All advertising materials mentioning features or use of this software
|
|
||||||
* must display the following acknowledgement:
|
|
||||||
* This product includes software developed by the University of
|
|
||||||
* California, Berkeley and its contributors.
|
|
||||||
* 4. Neither the name of the University nor the names of its contributors
|
* 4. Neither the name of the University nor the names of its contributors
|
||||||
* may be used to endorse or promote products derived from this software
|
* may be used to endorse or promote products derived from this software
|
||||||
* without specific prior written permission.
|
* without specific prior written permission.
|
||||||
|
@ -33,24 +29,21 @@
|
||||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||||
* SUCH DAMAGE.
|
* SUCH DAMAGE.
|
||||||
*
|
*
|
||||||
* @(#)redir.h 5.1 (Berkeley) 3/7/91
|
* @(#)redir.h 8.2 (Berkeley) 5/4/95
|
||||||
|
* $FreeBSD: src/bin/sh/redir.h,v 1.10 2004/04/06 20:06:51 markm Exp $
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* flags passed to redirect */
|
/* flags passed to redirect */
|
||||||
#define REDIR_PUSH 01 /* save previous values of file descriptors */
|
#define REDIR_PUSH 01 /* save previous values of file descriptors */
|
||||||
#define REDIR_BACKQ 02 /* save the command output in memory */
|
#define REDIR_BACKQ 02 /* save the command output in memory */
|
||||||
|
|
||||||
#ifdef __STDC__
|
|
||||||
union node;
|
union node;
|
||||||
void redirect(union node *, int);
|
void redirect(union node *, int);
|
||||||
void popredir(void);
|
void popredir(void);
|
||||||
void clearredir(void);
|
|
||||||
int copyfd(int, int);
|
|
||||||
int fd0_redirected_p(void);
|
int fd0_redirected_p(void);
|
||||||
#else
|
void clearredir(void);
|
||||||
void redirect();
|
|
||||||
void popredir();
|
|
||||||
void clearredir();
|
/*
|
||||||
int copyfd();
|
* $PchId: redir.h,v 1.3 2006/03/29 14:13:34 philip Exp $
|
||||||
int fd0_redirected_p();
|
*/
|
||||||
#endif
|
|
||||||
|
|
463
commands/ash/setmode.c
Normal file
463
commands/ash/setmode.c
Normal file
|
@ -0,0 +1,463 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 1989, 1993, 1994
|
||||||
|
* The Regents of the University of California. All rights reserved.
|
||||||
|
*
|
||||||
|
* This code is derived from software contributed to Berkeley by
|
||||||
|
* Dave Borman at Cray Research, Inc.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
* 1. Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* 3. All advertising materials mentioning features or use of this software
|
||||||
|
* must display the following acknowledgement:
|
||||||
|
* This product includes software developed by the University of
|
||||||
|
* California, Berkeley and its contributors.
|
||||||
|
* 4. Neither the name of the University nor the names of its contributors
|
||||||
|
* may be used to endorse or promote products derived from this software
|
||||||
|
* without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||||
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||||
|
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
|
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||||
|
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||||
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||||
|
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||||
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||||
|
* SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#if defined(LIBC_SCCS) && !defined(lint)
|
||||||
|
static char sccsid[] = "@(#)setmode.c 8.2 (Berkeley) 3/25/94";
|
||||||
|
#endif /* LIBC_SCCS and not lint */
|
||||||
|
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
|
||||||
|
#include <ctype.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <signal.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#ifdef SETMODE_DEBUG
|
||||||
|
#include <stdio.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "shell.h"
|
||||||
|
|
||||||
|
#ifndef S_ISTXT
|
||||||
|
#define S_ISTXT S_ISVTX
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define SET_LEN 6 /* initial # of bitcmd struct to malloc */
|
||||||
|
#define SET_LEN_INCR 4 /* # of bitcmd structs to add as needed */
|
||||||
|
|
||||||
|
typedef struct bitcmd {
|
||||||
|
char cmd;
|
||||||
|
char cmd2;
|
||||||
|
mode_t bits;
|
||||||
|
} BITCMD;
|
||||||
|
|
||||||
|
#define CMD2_CLR 0x01
|
||||||
|
#define CMD2_SET 0x02
|
||||||
|
#define CMD2_GBITS 0x04
|
||||||
|
#define CMD2_OBITS 0x08
|
||||||
|
#define CMD2_UBITS 0x10
|
||||||
|
|
||||||
|
static BITCMD *addcmd (BITCMD *, int, int, int, unsigned int);
|
||||||
|
static int compress_mode (BITCMD *);
|
||||||
|
#ifdef SETMODE_DEBUG
|
||||||
|
static void dumpmode __P((BITCMD *));
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Given the old mode and an array of bitcmd structures, apply the operations
|
||||||
|
* described in the bitcmd structures to the old mode, and return the new mode.
|
||||||
|
* Note that there is no '=' command; a strict assignment is just a '-' (clear
|
||||||
|
* bits) followed by a '+' (set bits).
|
||||||
|
*/
|
||||||
|
mode_t
|
||||||
|
getmode(bbox, omode)
|
||||||
|
void *bbox;
|
||||||
|
mode_t omode;
|
||||||
|
{
|
||||||
|
register BITCMD *set;
|
||||||
|
register mode_t clrval, newmode, value;
|
||||||
|
|
||||||
|
set = (BITCMD *)bbox;
|
||||||
|
newmode = omode;
|
||||||
|
for (value = 0;; set++)
|
||||||
|
switch(set->cmd) {
|
||||||
|
/*
|
||||||
|
* When copying the user, group or other bits around, we "know"
|
||||||
|
* where the bits are in the mode so that we can do shifts to
|
||||||
|
* copy them around. If we don't use shifts, it gets real
|
||||||
|
* grundgy with lots of single bit checks and bit sets.
|
||||||
|
*/
|
||||||
|
case 'u':
|
||||||
|
value = (newmode & S_IRWXU) >> 6;
|
||||||
|
goto common;
|
||||||
|
|
||||||
|
case 'g':
|
||||||
|
value = (newmode & S_IRWXG) >> 3;
|
||||||
|
goto common;
|
||||||
|
|
||||||
|
case 'o':
|
||||||
|
value = newmode & S_IRWXO;
|
||||||
|
common: if (set->cmd2 & CMD2_CLR) {
|
||||||
|
clrval =
|
||||||
|
(set->cmd2 & CMD2_SET) ? S_IRWXO : value;
|
||||||
|
if (set->cmd2 & CMD2_UBITS)
|
||||||
|
newmode &= ~((clrval<<6) & set->bits);
|
||||||
|
if (set->cmd2 & CMD2_GBITS)
|
||||||
|
newmode &= ~((clrval<<3) & set->bits);
|
||||||
|
if (set->cmd2 & CMD2_OBITS)
|
||||||
|
newmode &= ~(clrval & set->bits);
|
||||||
|
}
|
||||||
|
if (set->cmd2 & CMD2_SET) {
|
||||||
|
if (set->cmd2 & CMD2_UBITS)
|
||||||
|
newmode |= (value<<6) & set->bits;
|
||||||
|
if (set->cmd2 & CMD2_GBITS)
|
||||||
|
newmode |= (value<<3) & set->bits;
|
||||||
|
if (set->cmd2 & CMD2_OBITS)
|
||||||
|
newmode |= value & set->bits;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case '+':
|
||||||
|
newmode |= set->bits;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case '-':
|
||||||
|
newmode &= ~set->bits;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'X':
|
||||||
|
if (omode & (S_IFDIR|S_IXUSR|S_IXGRP|S_IXOTH))
|
||||||
|
newmode |= set->bits;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case '\0':
|
||||||
|
default:
|
||||||
|
#ifdef SETMODE_DEBUG
|
||||||
|
(void)printf("getmode:%04o -> %04o\n", omode, newmode);
|
||||||
|
#endif
|
||||||
|
return (newmode);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#define ADDCMD(a, b, c, d) \
|
||||||
|
if (set >= endset) { \
|
||||||
|
register BITCMD *newset; \
|
||||||
|
setlen += SET_LEN_INCR; \
|
||||||
|
newset = realloc(saveset, sizeof(BITCMD) * setlen); \
|
||||||
|
if (!saveset) \
|
||||||
|
return (NULL); \
|
||||||
|
set = newset + (set - saveset); \
|
||||||
|
saveset = newset; \
|
||||||
|
endset = newset + (setlen - 2); \
|
||||||
|
} \
|
||||||
|
set = addcmd(set, (a), (b), (c), (d))
|
||||||
|
|
||||||
|
#define STANDARD_BITS (S_ISUID|S_ISGID|S_IRWXU|S_IRWXG|S_IRWXO)
|
||||||
|
|
||||||
|
void *
|
||||||
|
setmode(p)
|
||||||
|
register char *p;
|
||||||
|
{
|
||||||
|
register int perm, who;
|
||||||
|
register char op;
|
||||||
|
BITCMD *set, *saveset, *endset;
|
||||||
|
sigset_t sigset, sigoset;
|
||||||
|
mode_t mask;
|
||||||
|
int equalopdone, permXbits, setlen;
|
||||||
|
|
||||||
|
if (!*p)
|
||||||
|
return (NULL);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Get a copy of the mask for the permissions that are mask relative.
|
||||||
|
* Flip the bits, we want what's not set. Since it's possible that
|
||||||
|
* the caller is opening files inside a signal handler, protect them
|
||||||
|
* as best we can.
|
||||||
|
*/
|
||||||
|
sigfillset(&sigset);
|
||||||
|
(void)sigprocmask(SIG_BLOCK, &sigset, &sigoset);
|
||||||
|
(void)umask(mask = umask(0));
|
||||||
|
mask = ~mask;
|
||||||
|
(void)sigprocmask(SIG_SETMASK, &sigoset, NULL);
|
||||||
|
|
||||||
|
setlen = SET_LEN + 2;
|
||||||
|
|
||||||
|
if ((set = malloc((unsigned int)(sizeof(BITCMD) * setlen))) == NULL)
|
||||||
|
return (NULL);
|
||||||
|
saveset = set;
|
||||||
|
endset = set + (setlen - 2);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If an absolute number, get it and return; disallow non-octal digits
|
||||||
|
* or illegal bits.
|
||||||
|
*/
|
||||||
|
if (isdigit(*p)) {
|
||||||
|
perm = (mode_t)strtol(p, NULL, 8);
|
||||||
|
if (perm & ~(STANDARD_BITS|S_ISTXT)) {
|
||||||
|
free(saveset);
|
||||||
|
return (NULL);
|
||||||
|
}
|
||||||
|
while (*++p)
|
||||||
|
if (*p < '0' || *p > '7') {
|
||||||
|
free(saveset);
|
||||||
|
return (NULL);
|
||||||
|
}
|
||||||
|
ADDCMD('=', (STANDARD_BITS|S_ISTXT), perm, mask);
|
||||||
|
return (saveset);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Build list of structures to set/clear/copy bits as described by
|
||||||
|
* each clause of the symbolic mode.
|
||||||
|
*/
|
||||||
|
for (;;) {
|
||||||
|
/* First, find out which bits might be modified. */
|
||||||
|
for (who = 0;; ++p) {
|
||||||
|
switch (*p) {
|
||||||
|
case 'a':
|
||||||
|
who |= STANDARD_BITS;
|
||||||
|
break;
|
||||||
|
case 'u':
|
||||||
|
who |= S_ISUID|S_IRWXU;
|
||||||
|
break;
|
||||||
|
case 'g':
|
||||||
|
who |= S_ISGID|S_IRWXG;
|
||||||
|
break;
|
||||||
|
case 'o':
|
||||||
|
who |= S_IRWXO;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
goto getop;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
getop: if ((op = *p++) != '+' && op != '-' && op != '=') {
|
||||||
|
free(saveset);
|
||||||
|
return (NULL);
|
||||||
|
}
|
||||||
|
if (op == '=')
|
||||||
|
equalopdone = 0;
|
||||||
|
|
||||||
|
who &= ~S_ISTXT;
|
||||||
|
for (perm = 0, permXbits = 0;; ++p) {
|
||||||
|
switch (*p) {
|
||||||
|
case 'r':
|
||||||
|
perm |= S_IRUSR|S_IRGRP|S_IROTH;
|
||||||
|
break;
|
||||||
|
case 's':
|
||||||
|
/* If only "other" bits ignore set-id. */
|
||||||
|
if (who & ~S_IRWXO)
|
||||||
|
perm |= S_ISUID|S_ISGID;
|
||||||
|
break;
|
||||||
|
case 't':
|
||||||
|
/* If only "other" bits ignore sticky. */
|
||||||
|
if (who & ~S_IRWXO) {
|
||||||
|
who |= S_ISTXT;
|
||||||
|
perm |= S_ISTXT;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 'w':
|
||||||
|
perm |= S_IWUSR|S_IWGRP|S_IWOTH;
|
||||||
|
break;
|
||||||
|
case 'X':
|
||||||
|
permXbits = S_IXUSR|S_IXGRP|S_IXOTH;
|
||||||
|
break;
|
||||||
|
case 'x':
|
||||||
|
perm |= S_IXUSR|S_IXGRP|S_IXOTH;
|
||||||
|
break;
|
||||||
|
case 'u':
|
||||||
|
case 'g':
|
||||||
|
case 'o':
|
||||||
|
/*
|
||||||
|
* When ever we hit 'u', 'g', or 'o', we have
|
||||||
|
* to flush out any partial mode that we have,
|
||||||
|
* and then do the copying of the mode bits.
|
||||||
|
*/
|
||||||
|
if (perm) {
|
||||||
|
ADDCMD(op, who, perm, mask);
|
||||||
|
perm = 0;
|
||||||
|
}
|
||||||
|
if (op == '=')
|
||||||
|
equalopdone = 1;
|
||||||
|
if (op == '+' && permXbits) {
|
||||||
|
ADDCMD('X', who, permXbits, mask);
|
||||||
|
permXbits = 0;
|
||||||
|
}
|
||||||
|
ADDCMD(*p, who, op, mask);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
/*
|
||||||
|
* Add any permissions that we haven't already
|
||||||
|
* done.
|
||||||
|
*/
|
||||||
|
if (perm || (op == '=' && !equalopdone)) {
|
||||||
|
if (op == '=')
|
||||||
|
equalopdone = 1;
|
||||||
|
ADDCMD(op, who, perm, mask);
|
||||||
|
perm = 0;
|
||||||
|
}
|
||||||
|
if (permXbits) {
|
||||||
|
ADDCMD('X', who, permXbits, mask);
|
||||||
|
permXbits = 0;
|
||||||
|
}
|
||||||
|
goto apply;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
apply: if (!*p)
|
||||||
|
break;
|
||||||
|
if (*p != ',')
|
||||||
|
goto getop;
|
||||||
|
++p;
|
||||||
|
}
|
||||||
|
set->cmd = 0;
|
||||||
|
#ifdef SETMODE_DEBUG
|
||||||
|
(void)printf("Before compress_mode()\n");
|
||||||
|
dumpmode(saveset);
|
||||||
|
#endif
|
||||||
|
compress_mode(saveset);
|
||||||
|
#ifdef SETMODE_DEBUG
|
||||||
|
(void)printf("After compress_mode()\n");
|
||||||
|
dumpmode(saveset);
|
||||||
|
#endif
|
||||||
|
return (saveset);
|
||||||
|
}
|
||||||
|
|
||||||
|
static BITCMD *
|
||||||
|
addcmd(set, op, who, oparg, mask)
|
||||||
|
BITCMD *set;
|
||||||
|
register int oparg, who;
|
||||||
|
register int op;
|
||||||
|
unsigned int mask;
|
||||||
|
{
|
||||||
|
switch (op) {
|
||||||
|
case '=':
|
||||||
|
set->cmd = '-';
|
||||||
|
set->bits = who ? who : STANDARD_BITS;
|
||||||
|
set++;
|
||||||
|
|
||||||
|
op = '+';
|
||||||
|
/* FALLTHROUGH */
|
||||||
|
case '+':
|
||||||
|
case '-':
|
||||||
|
case 'X':
|
||||||
|
set->cmd = op;
|
||||||
|
set->bits = (who ? who : mask) & oparg;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'u':
|
||||||
|
case 'g':
|
||||||
|
case 'o':
|
||||||
|
set->cmd = op;
|
||||||
|
if (who) {
|
||||||
|
set->cmd2 = ((who & S_IRUSR) ? CMD2_UBITS : 0) |
|
||||||
|
((who & S_IRGRP) ? CMD2_GBITS : 0) |
|
||||||
|
((who & S_IROTH) ? CMD2_OBITS : 0);
|
||||||
|
set->bits = ~0;
|
||||||
|
} else {
|
||||||
|
set->cmd2 = CMD2_UBITS | CMD2_GBITS | CMD2_OBITS;
|
||||||
|
set->bits = mask;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (oparg == '+')
|
||||||
|
set->cmd2 |= CMD2_SET;
|
||||||
|
else if (oparg == '-')
|
||||||
|
set->cmd2 |= CMD2_CLR;
|
||||||
|
else if (oparg == '=')
|
||||||
|
set->cmd2 |= CMD2_SET|CMD2_CLR;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return (set + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef SETMODE_DEBUG
|
||||||
|
static void
|
||||||
|
dumpmode(set)
|
||||||
|
register BITCMD *set;
|
||||||
|
{
|
||||||
|
for (; set->cmd; ++set)
|
||||||
|
(void)printf("cmd: '%c' bits %04o%s%s%s%s%s%s\n",
|
||||||
|
set->cmd, set->bits, set->cmd2 ? " cmd2:" : "",
|
||||||
|
set->cmd2 & CMD2_CLR ? " CLR" : "",
|
||||||
|
set->cmd2 & CMD2_SET ? " SET" : "",
|
||||||
|
set->cmd2 & CMD2_UBITS ? " UBITS" : "",
|
||||||
|
set->cmd2 & CMD2_GBITS ? " GBITS" : "",
|
||||||
|
set->cmd2 & CMD2_OBITS ? " OBITS" : "");
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Given an array of bitcmd structures, compress by compacting consecutive
|
||||||
|
* '+', '-' and 'X' commands into at most 3 commands, one of each. The 'u',
|
||||||
|
* 'g' and 'o' commands continue to be separate. They could probably be
|
||||||
|
* compacted, but it's not worth the effort.
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
compress_mode(set)
|
||||||
|
register BITCMD *set;
|
||||||
|
{
|
||||||
|
register BITCMD *nset;
|
||||||
|
register int setbits, clrbits, Xbits, op;
|
||||||
|
|
||||||
|
for (nset = set;;) {
|
||||||
|
/* Copy over any 'u', 'g' and 'o' commands. */
|
||||||
|
while ((op = nset->cmd) != '+' && op != '-' && op != 'X') {
|
||||||
|
*set++ = *nset++;
|
||||||
|
if (!op)
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (setbits = clrbits = Xbits = 0;; nset++) {
|
||||||
|
if ((op = nset->cmd) == '-') {
|
||||||
|
clrbits |= nset->bits;
|
||||||
|
setbits &= ~nset->bits;
|
||||||
|
Xbits &= ~nset->bits;
|
||||||
|
} else if (op == '+') {
|
||||||
|
setbits |= nset->bits;
|
||||||
|
clrbits &= ~nset->bits;
|
||||||
|
Xbits &= ~nset->bits;
|
||||||
|
} else if (op == 'X')
|
||||||
|
Xbits |= nset->bits & ~setbits;
|
||||||
|
else
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (clrbits) {
|
||||||
|
set->cmd = '-';
|
||||||
|
set->cmd2 = 0;
|
||||||
|
set->bits = clrbits;
|
||||||
|
set++;
|
||||||
|
}
|
||||||
|
if (setbits) {
|
||||||
|
set->cmd = '+';
|
||||||
|
set->cmd2 = 0;
|
||||||
|
set->bits = setbits;
|
||||||
|
set++;
|
||||||
|
}
|
||||||
|
if (Xbits) {
|
||||||
|
set->cmd = 'X';
|
||||||
|
set->cmd2 = 0;
|
||||||
|
set->bits = Xbits;
|
||||||
|
set++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* $PchId: setmode.c,v 1.3 2006/05/23 11:57:34 philip Exp $
|
||||||
|
*/
|
|
@ -1,6 +1,6 @@
|
||||||
/*-
|
/*-
|
||||||
* Copyright (c) 1991 The Regents of the University of California.
|
* Copyright (c) 1991, 1993
|
||||||
* All rights reserved.
|
* The Regents of the University of California. All rights reserved.
|
||||||
*
|
*
|
||||||
* This code is derived from software contributed to Berkeley by
|
* This code is derived from software contributed to Berkeley by
|
||||||
* Kenneth Almquist.
|
* Kenneth Almquist.
|
||||||
|
@ -13,10 +13,6 @@
|
||||||
* 2. Redistributions in binary form must reproduce the above copyright
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
* notice, this list of conditions and the following disclaimer in the
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
* documentation and/or other materials provided with the distribution.
|
* documentation and/or other materials provided with the distribution.
|
||||||
* 3. All advertising materials mentioning features or use of this software
|
|
||||||
* must display the following acknowledgement:
|
|
||||||
* This product includes software developed by the University of
|
|
||||||
* California, Berkeley and its contributors.
|
|
||||||
* 4. Neither the name of the University nor the names of its contributors
|
* 4. Neither the name of the University nor the names of its contributors
|
||||||
* may be used to endorse or promote products derived from this software
|
* may be used to endorse or promote products derived from this software
|
||||||
* without specific prior written permission.
|
* without specific prior written permission.
|
||||||
|
@ -33,19 +29,17 @@
|
||||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||||
* SUCH DAMAGE.
|
* SUCH DAMAGE.
|
||||||
*
|
*
|
||||||
* @(#)shell.h 5.4 (Berkeley) 4/12/91
|
* @(#)shell.h 8.2 (Berkeley) 5/4/95
|
||||||
|
* $FreeBSD: src/bin/sh/shell.h,v 1.17 2004/04/06 20:06:51 markm Exp $
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <sys/types.h> /* for mode_t */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The follow should be set to reflect the type of system you have:
|
* The follow should be set to reflect the type of system you have:
|
||||||
* JOBS -> 1 if you have Berkeley job control, 0 otherwise.
|
* JOBS -> 1 if you have Berkeley job control, 0 otherwise.
|
||||||
* SYMLINKS -> 1 if your system includes symbolic links, 0 otherwise.
|
|
||||||
* DIRENT -> 1 if your system has the SVR3 directory(3X) routines.
|
|
||||||
* UDIR -> 1 if you want the shell to simulate the /u directory.
|
|
||||||
* TILDE -> 1 if you want the shell to expand ~logname.
|
* TILDE -> 1 if you want the shell to expand ~logname.
|
||||||
* USEGETPW -> 1 if getpwnam() must be used to look up a name.
|
* USEGETPW -> 1 if getpwnam() must be used to look up a name.
|
||||||
* ATTY -> 1 to include code for atty(1).
|
|
||||||
* SHORTNAMES -> 1 if your linker cannot handle long names.
|
|
||||||
* READLINE -> 1 if line editing by readline() should be enabled.
|
* READLINE -> 1 if line editing by readline() should be enabled.
|
||||||
* define BSD if you are running 4.2 BSD or later.
|
* define BSD if you are running 4.2 BSD or later.
|
||||||
* define SYSV if you are running under System V.
|
* define SYSV if you are running under System V.
|
||||||
|
@ -56,52 +50,47 @@
|
||||||
* a quit signal will generate a core dump.
|
* a quit signal will generate a core dump.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#ifndef JOBS
|
||||||
#define JOBS 0
|
#define JOBS 1
|
||||||
|
|
||||||
/* Set SYMLINKS to 0 by request of Giovanni Falzoni, who wrote the
|
|
||||||
* symlink patches for Minix; email to minix-devel-l of thu 3 nov.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#if 0
|
|
||||||
#define SYMLINKS defined(S_ISLNK)
|
|
||||||
#else
|
|
||||||
#define SYMLINKS 0
|
|
||||||
#endif
|
#endif
|
||||||
|
#ifndef BSD
|
||||||
#define DIRENT 1
|
#define BSD 1
|
||||||
#define UDIR 0
|
#endif
|
||||||
#define TILDE 1
|
#ifndef DEBUG
|
||||||
#define USEGETPW 0
|
|
||||||
#define ATTY 0
|
|
||||||
#define READLINE 1
|
|
||||||
#define HASHBANG 0
|
|
||||||
/* #define BSD */
|
|
||||||
#define POSIX 1
|
|
||||||
#define DEBUG 0
|
#define DEBUG 0
|
||||||
|
#endif
|
||||||
|
#define POSIX 1
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Type of used arithmetics. SUSv3 requires us to have at least signed long.
|
||||||
|
*/
|
||||||
|
typedef long arith_t;
|
||||||
|
#define ARITH_FORMAT_STR "%ld"
|
||||||
|
#define atoarith_t(arg) strtol(arg, NULL, 0)
|
||||||
|
#define strtoarith_t(nptr, endptr, base) strtol(nptr, endptr, base)
|
||||||
|
|
||||||
#ifdef __STDC__
|
|
||||||
typedef void *pointer;
|
typedef void *pointer;
|
||||||
#ifndef NULL
|
#define STATIC static
|
||||||
#define NULL (void *)0
|
|
||||||
#endif
|
|
||||||
#else /* not __STDC__ */
|
|
||||||
typedef char *pointer;
|
|
||||||
#ifndef NULL
|
|
||||||
#define NULL 0
|
|
||||||
#endif
|
|
||||||
#endif /* not __STDC__ */
|
|
||||||
#define STATIC /* empty */
|
|
||||||
#define MKINIT /* empty */
|
#define MKINIT /* empty */
|
||||||
|
|
||||||
#include <sys/cdefs.h>
|
|
||||||
#include <sys/types.h>
|
|
||||||
|
|
||||||
extern char nullstr[1]; /* null string */
|
extern char nullstr[1]; /* null string */
|
||||||
|
|
||||||
|
|
||||||
#if DEBUG
|
#if DEBUG
|
||||||
#define TRACE(param) trace param
|
#define TRACE(param) sh_trace param
|
||||||
#else
|
#else
|
||||||
#define TRACE(param)
|
#define TRACE(param)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef __minix
|
||||||
|
#define __unused
|
||||||
|
|
||||||
|
typedef long quad_t; /* XXX */
|
||||||
|
typedef unsigned long u_quad_t; /* XXX */
|
||||||
|
#endif
|
||||||
|
|
||||||
|
mode_t getmode(void *, int /* mode_t */);
|
||||||
|
void *setmode(char *);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* $PchId: shell.h,v 1.7 2006/05/22 12:47:00 philip Exp $
|
||||||
|
*/
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/*-
|
/*-
|
||||||
* Copyright (c) 1991 The Regents of the University of California.
|
* Copyright (c) 1991, 1993
|
||||||
* All rights reserved.
|
* The Regents of the University of California. All rights reserved.
|
||||||
*
|
*
|
||||||
* This code is derived from software contributed to Berkeley by
|
* This code is derived from software contributed to Berkeley by
|
||||||
* Kenneth Almquist.
|
* Kenneth Almquist.
|
||||||
|
@ -13,10 +13,6 @@
|
||||||
* 2. Redistributions in binary form must reproduce the above copyright
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
* notice, this list of conditions and the following disclaimer in the
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
* documentation and/or other materials provided with the distribution.
|
* documentation and/or other materials provided with the distribution.
|
||||||
* 3. All advertising materials mentioning features or use of this software
|
|
||||||
* must display the following acknowledgement:
|
|
||||||
* This product includes software developed by the University of
|
|
||||||
* California, Berkeley and its contributors.
|
|
||||||
* 4. Neither the name of the University nor the names of its contributors
|
* 4. Neither the name of the University nor the names of its contributors
|
||||||
* may be used to endorse or promote products derived from this software
|
* may be used to endorse or promote products derived from this software
|
||||||
* without specific prior written permission.
|
* without specific prior written permission.
|
||||||
|
@ -35,38 +31,54 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef lint
|
#ifndef lint
|
||||||
static char sccsid[] = "@(#)show.c 5.2 (Berkeley) 4/12/91";
|
#if 0
|
||||||
|
static char sccsid[] = "@(#)show.c 8.3 (Berkeley) 5/4/95";
|
||||||
|
#endif
|
||||||
#endif /* not lint */
|
#endif /* not lint */
|
||||||
|
/*
|
||||||
|
#include <sys/cdefs.h>
|
||||||
|
__FBSDID("$FreeBSD: src/bin/sh/show.c,v 1.21 2004/04/06 20:06:51 markm Exp $");
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <fcntl.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdarg.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
|
|
||||||
#include "shell.h"
|
#include "shell.h"
|
||||||
#include "parser.h"
|
#include "parser.h"
|
||||||
#include "nodes.h"
|
#include "nodes.h"
|
||||||
#include "mystring.h"
|
#include "mystring.h"
|
||||||
|
#include "show.h"
|
||||||
|
|
||||||
#if DEBUG
|
#if DEBUG
|
||||||
static shtree(), shcmd(), sharg(), indent();
|
static void trputc(int c);
|
||||||
|
static void shtree(union node *, int, char *, FILE*);
|
||||||
|
static void shcmd(union node *, FILE *);
|
||||||
|
static void sharg(union node *, FILE *);
|
||||||
|
static void indent(int, char *, FILE *);
|
||||||
|
static void trstring(char *);
|
||||||
|
static void showtree(union node *n);
|
||||||
|
|
||||||
|
|
||||||
showtree(n)
|
static void
|
||||||
union node *n;
|
showtree(union node *n)
|
||||||
{
|
{
|
||||||
trputs("showtree called\n");
|
trputs("showtree called\n");
|
||||||
shtree(n, 1, NULL, stdout);
|
shtree(n, 1, NULL, stdout);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static
|
static void
|
||||||
shtree(n, ind, pfx, fp)
|
shtree(union node *n, int ind, char *pfx, FILE *fp)
|
||||||
union node *n;
|
|
||||||
char *pfx;
|
|
||||||
FILE *fp;
|
|
||||||
{
|
{
|
||||||
struct nodelist *lp;
|
struct nodelist *lp;
|
||||||
char *s;
|
char *s;
|
||||||
|
|
||||||
|
if (n == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
indent(ind, pfx, fp);
|
indent(ind, pfx, fp);
|
||||||
switch(n->type) {
|
switch(n->type) {
|
||||||
case NSEMI:
|
case NSEMI:
|
||||||
|
@ -109,10 +121,8 @@ binop:
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static
|
static void
|
||||||
shcmd(cmd, fp)
|
shcmd(union node *cmd, FILE *fp)
|
||||||
union node *cmd;
|
|
||||||
FILE *fp;
|
|
||||||
{
|
{
|
||||||
union node *np;
|
union node *np;
|
||||||
int first;
|
int first;
|
||||||
|
@ -133,14 +143,20 @@ shcmd(cmd, fp)
|
||||||
case NTO: s = ">"; dftfd = 1; break;
|
case NTO: s = ">"; dftfd = 1; break;
|
||||||
case NAPPEND: s = ">>"; dftfd = 1; break;
|
case NAPPEND: s = ">>"; dftfd = 1; break;
|
||||||
case NTOFD: s = ">&"; dftfd = 1; break;
|
case NTOFD: s = ">&"; dftfd = 1; break;
|
||||||
|
case NCLOBBER: s = ">|"; dftfd = 1; break;
|
||||||
case NFROM: s = "<"; dftfd = 0; break;
|
case NFROM: s = "<"; dftfd = 0; break;
|
||||||
|
case NFROMTO: s = "<>"; dftfd = 0; break;
|
||||||
case NFROMFD: s = "<&"; dftfd = 0; break;
|
case NFROMFD: s = "<&"; dftfd = 0; break;
|
||||||
|
default: s = "*error*"; dftfd = 0; break;
|
||||||
}
|
}
|
||||||
if (np->nfile.fd != dftfd)
|
if (np->nfile.fd != dftfd)
|
||||||
fprintf(fp, "%d", np->nfile.fd);
|
fprintf(fp, "%d", np->nfile.fd);
|
||||||
fputs(s, fp);
|
fputs(s, fp);
|
||||||
if (np->nfile.type == NTOFD || np->nfile.type == NFROMFD) {
|
if (np->nfile.type == NTOFD || np->nfile.type == NFROMFD) {
|
||||||
|
if (np->ndup.dupfd >= 0)
|
||||||
fprintf(fp, "%d", np->ndup.dupfd);
|
fprintf(fp, "%d", np->ndup.dupfd);
|
||||||
|
else
|
||||||
|
fprintf(fp, "-");
|
||||||
} else {
|
} else {
|
||||||
sharg(np->nfile.fname, fp);
|
sharg(np->nfile.fname, fp);
|
||||||
}
|
}
|
||||||
|
@ -150,10 +166,8 @@ shcmd(cmd, fp)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static
|
static void
|
||||||
sharg(arg, fp)
|
sharg(union node *arg, FILE *fp)
|
||||||
union node *arg;
|
|
||||||
FILE *fp;
|
|
||||||
{
|
{
|
||||||
char *p;
|
char *p;
|
||||||
struct nodelist *bqlist;
|
struct nodelist *bqlist;
|
||||||
|
@ -174,10 +188,15 @@ sharg(arg, fp)
|
||||||
putc('$', fp);
|
putc('$', fp);
|
||||||
putc('{', fp);
|
putc('{', fp);
|
||||||
subtype = *++p;
|
subtype = *++p;
|
||||||
|
if (subtype == VSLENGTH)
|
||||||
|
putc('#', fp);
|
||||||
|
|
||||||
while (*p != '=')
|
while (*p != '=')
|
||||||
putc(*p++, fp);
|
putc(*p++, fp);
|
||||||
|
|
||||||
if (subtype & VSNUL)
|
if (subtype & VSNUL)
|
||||||
putc(':', fp);
|
putc(':', fp);
|
||||||
|
|
||||||
switch (subtype & VSTYPE) {
|
switch (subtype & VSTYPE) {
|
||||||
case VSNORMAL:
|
case VSNORMAL:
|
||||||
putc('}', fp);
|
putc('}', fp);
|
||||||
|
@ -194,6 +213,22 @@ sharg(arg, fp)
|
||||||
case VSASSIGN:
|
case VSASSIGN:
|
||||||
putc('=', fp);
|
putc('=', fp);
|
||||||
break;
|
break;
|
||||||
|
case VSTRIMLEFT:
|
||||||
|
putc('#', fp);
|
||||||
|
break;
|
||||||
|
case VSTRIMLEFTMAX:
|
||||||
|
putc('#', fp);
|
||||||
|
putc('#', fp);
|
||||||
|
break;
|
||||||
|
case VSTRIMRIGHT:
|
||||||
|
putc('%', fp);
|
||||||
|
break;
|
||||||
|
case VSTRIMRIGHTMAX:
|
||||||
|
putc('%', fp);
|
||||||
|
putc('%', fp);
|
||||||
|
break;
|
||||||
|
case VSLENGTH:
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
printf("<subtype %d>", subtype);
|
printf("<subtype %d>", subtype);
|
||||||
}
|
}
|
||||||
|
@ -216,10 +251,8 @@ sharg(arg, fp)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static
|
static void
|
||||||
indent(amount, pfx, fp)
|
indent(int amount, char *pfx, FILE *fp)
|
||||||
char *pfx;
|
|
||||||
FILE *fp;
|
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
|
@ -229,8 +262,6 @@ indent(amount, pfx, fp)
|
||||||
putc('\t', fp);
|
putc('\t', fp);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -247,52 +278,48 @@ int debug = 0;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
trputc(c) {
|
static void
|
||||||
#if DEBUG
|
trputc(int c)
|
||||||
|
{
|
||||||
if (tracefile == NULL)
|
if (tracefile == NULL)
|
||||||
return;
|
return;
|
||||||
putc(c, tracefile);
|
putc(c, tracefile);
|
||||||
if (c == '\n')
|
if (c == '\n')
|
||||||
fflush(tracefile);
|
fflush(tracefile);
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
trace(fmt, a1, a2, a3, a4, a5, a6, a7, a8)
|
void
|
||||||
char *fmt;
|
sh_trace(const char *fmt, ...)
|
||||||
{
|
{
|
||||||
#if DEBUG
|
va_list va;
|
||||||
int e = errno;
|
va_start(va, fmt);
|
||||||
if (tracefile == NULL)
|
if (tracefile != NULL) {
|
||||||
return;
|
(void) vfprintf(tracefile, fmt, va);
|
||||||
fprintf(tracefile, fmt, a1, a2, a3, a4, a5, a6, a7, a8);
|
|
||||||
if (strchr(fmt, '\n'))
|
if (strchr(fmt, '\n'))
|
||||||
fflush(tracefile);
|
(void) fflush(tracefile);
|
||||||
errno = e;
|
}
|
||||||
#endif
|
va_end(va);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
trputs(s)
|
void
|
||||||
char *s;
|
trputs(char *s)
|
||||||
{
|
{
|
||||||
#if DEBUG
|
|
||||||
if (tracefile == NULL)
|
if (tracefile == NULL)
|
||||||
return;
|
return;
|
||||||
fputs(s, tracefile);
|
fputs(s, tracefile);
|
||||||
if (strchr(s, '\n'))
|
if (strchr(s, '\n'))
|
||||||
fflush(tracefile);
|
fflush(tracefile);
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
trstring(s)
|
static void
|
||||||
char *s;
|
trstring(char *s)
|
||||||
{
|
{
|
||||||
register char *p;
|
char *p;
|
||||||
char c;
|
char c;
|
||||||
|
|
||||||
#if DEBUG
|
|
||||||
if (tracefile == NULL)
|
if (tracefile == NULL)
|
||||||
return;
|
return;
|
||||||
putc('"', tracefile);
|
putc('"', tracefile);
|
||||||
|
@ -324,14 +351,12 @@ backslash: putc('\\', tracefile);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
putc('"', tracefile);
|
putc('"', tracefile);
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
trargs(ap)
|
void
|
||||||
char **ap;
|
trargs(char **ap)
|
||||||
{
|
{
|
||||||
#if DEBUG
|
|
||||||
if (tracefile == NULL)
|
if (tracefile == NULL)
|
||||||
return;
|
return;
|
||||||
while (*ap) {
|
while (*ap) {
|
||||||
|
@ -342,36 +367,43 @@ trargs(ap)
|
||||||
putc('\n', tracefile);
|
putc('\n', tracefile);
|
||||||
}
|
}
|
||||||
fflush(tracefile);
|
fflush(tracefile);
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
opentrace() {
|
void
|
||||||
|
opentrace(void)
|
||||||
|
{
|
||||||
char s[100];
|
char s[100];
|
||||||
char *p;
|
|
||||||
char *getenv();
|
|
||||||
int flags;
|
int flags;
|
||||||
|
|
||||||
#if DEBUG
|
|
||||||
if (!debug)
|
if (!debug)
|
||||||
return;
|
return;
|
||||||
|
#ifdef not_this_way
|
||||||
|
{
|
||||||
|
char *p;
|
||||||
if ((p = getenv("HOME")) == NULL) {
|
if ((p = getenv("HOME")) == NULL) {
|
||||||
if (getuid() == 0)
|
if (geteuid() == 0)
|
||||||
p = "/";
|
p = "/";
|
||||||
else
|
else
|
||||||
p = "/tmp";
|
p = "/tmp";
|
||||||
}
|
}
|
||||||
scopy(p, s);
|
scopy(p, s);
|
||||||
strcat(s, "/trace");
|
strcat(s, "/trace");
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
scopy("./trace", s);
|
||||||
|
#endif /* not_this_way */
|
||||||
if ((tracefile = fopen(s, "a")) == NULL) {
|
if ((tracefile = fopen(s, "a")) == NULL) {
|
||||||
fprintf(stderr, "Can't open %s\n", s);
|
fprintf(stderr, "Can't open %s: %s\n", s, strerror(errno));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
#ifdef O_APPEND
|
|
||||||
if ((flags = fcntl(fileno(tracefile), F_GETFL, 0)) >= 0)
|
if ((flags = fcntl(fileno(tracefile), F_GETFL, 0)) >= 0)
|
||||||
fcntl(fileno(tracefile), F_SETFL, flags | O_APPEND);
|
fcntl(fileno(tracefile), F_SETFL, flags | O_APPEND);
|
||||||
#endif
|
|
||||||
fputs("\nTracing started.\n", tracefile);
|
fputs("\nTracing started.\n", tracefile);
|
||||||
fflush(tracefile);
|
fflush(tracefile);
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
#endif /* DEBUG */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* $PchId: show.c,v 1.6 2006/05/22 12:27:51 philip Exp $
|
||||||
|
*/
|
||||||
|
|
42
commands/ash/show.h
Normal file
42
commands/ash/show.h
Normal file
|
@ -0,0 +1,42 @@
|
||||||
|
/*-
|
||||||
|
* Copyright (c) 1995
|
||||||
|
* The Regents of the University of California. All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
* 1. Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* 4. Neither the name of the University nor the names of its contributors
|
||||||
|
* may be used to endorse or promote products derived from this software
|
||||||
|
* without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||||
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||||
|
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
|
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||||
|
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||||
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||||
|
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||||
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||||
|
* SUCH DAMAGE.
|
||||||
|
*
|
||||||
|
* @(#)show.h 1.1 (Berkeley) 5/4/95
|
||||||
|
* $FreeBSD: src/bin/sh/show.h,v 1.11 2004/04/06 20:06:51 markm Exp $
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifdef DEBUG
|
||||||
|
void sh_trace(const char *, ...);
|
||||||
|
void trargs(char **);
|
||||||
|
void trputs(char *);
|
||||||
|
void opentrace(void);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
* $PchId: show.h,v 1.4 2006/03/29 13:28:45 philip Exp $
|
||||||
|
*/
|
|
@ -1,15 +0,0 @@
|
||||||
/* Replacement for something BSD has in sys/cdefs.h. */
|
|
||||||
|
|
||||||
#ifndef _ASH_SYS_CDEFS
|
|
||||||
#define _ASH_SYS_CDEFS
|
|
||||||
|
|
||||||
#if __STDC__
|
|
||||||
#define __P(params) params
|
|
||||||
#else
|
|
||||||
#define __P(params) ()
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Probably in sys/types.h. */
|
|
||||||
typedef void (*sig_t) __P(( int ));
|
|
||||||
|
|
||||||
#endif /* _ASH_SYS_CDEFS */
|
|
File diff suppressed because it is too large
Load diff
|
@ -1,6 +1,6 @@
|
||||||
/*-
|
/*-
|
||||||
* Copyright (c) 1991 The Regents of the University of California.
|
* Copyright (c) 1991, 1993
|
||||||
* All rights reserved.
|
* The Regents of the University of California. All rights reserved.
|
||||||
*
|
*
|
||||||
* This code is derived from software contributed to Berkeley by
|
* This code is derived from software contributed to Berkeley by
|
||||||
* Kenneth Almquist.
|
* Kenneth Almquist.
|
||||||
|
@ -13,10 +13,6 @@
|
||||||
* 2. Redistributions in binary form must reproduce the above copyright
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
* notice, this list of conditions and the following disclaimer in the
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
* documentation and/or other materials provided with the distribution.
|
* documentation and/or other materials provided with the distribution.
|
||||||
* 3. All advertising materials mentioning features or use of this software
|
|
||||||
* must display the following acknowledgement:
|
|
||||||
* This product includes software developed by the University of
|
|
||||||
* California, Berkeley and its contributors.
|
|
||||||
* 4. Neither the name of the University nor the names of its contributors
|
* 4. Neither the name of the University nor the names of its contributors
|
||||||
* may be used to endorse or promote products derived from this software
|
* may be used to endorse or promote products derived from this software
|
||||||
* without specific prior written permission.
|
* without specific prior written permission.
|
||||||
|
@ -35,25 +31,45 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef lint
|
#ifndef lint
|
||||||
static char sccsid[] = "@(#)trap.c 5.2 (Berkeley) 4/12/91";
|
#if 0
|
||||||
|
static char sccsid[] = "@(#)trap.c 8.5 (Berkeley) 6/5/95";
|
||||||
|
#endif
|
||||||
#endif /* not lint */
|
#endif /* not lint */
|
||||||
|
/*
|
||||||
|
#include <sys/cdefs.h>
|
||||||
|
__FBSDID("$FreeBSD: src/bin/sh/trap.c,v 1.29 2004/04/06 20:06:51 markm Exp $");
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <signal.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
#include "shell.h"
|
#include "shell.h"
|
||||||
#include "main.h"
|
#include "main.h"
|
||||||
#include "nodes.h" /* for other headers */
|
#include "nodes.h" /* for other headers */
|
||||||
#include "eval.h"
|
#include "eval.h"
|
||||||
#include "jobs.h"
|
#include "jobs.h"
|
||||||
|
#include "show.h"
|
||||||
#include "options.h"
|
#include "options.h"
|
||||||
#include "syntax.h"
|
#include "syntax.h"
|
||||||
#include "signames.h"
|
|
||||||
#include "output.h"
|
#include "output.h"
|
||||||
#include "memalloc.h"
|
#include "memalloc.h"
|
||||||
#include "error.h"
|
#include "error.h"
|
||||||
#include "trap.h"
|
#include "trap.h"
|
||||||
#include "mystring.h"
|
#include "mystring.h"
|
||||||
#include <sys/types.h>
|
#if !defined(NO_HISTORY) && !defined(EDITLINE)
|
||||||
#include <signal.h>
|
#include "myhistedit.h"
|
||||||
|
#endif
|
||||||
|
#include "builtins.h"
|
||||||
|
|
||||||
|
#ifdef __minix
|
||||||
|
#define NO_SIGINTERRUPT
|
||||||
|
#define NO_SYS_SIGNAME
|
||||||
|
#define NO_SYS_SIGLIST
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
typedef void (*sig_T)(int);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Sigmode records the current value of the signal handlers for the various
|
* Sigmode records the current value of the signal handlers for the various
|
||||||
|
@ -64,40 +80,130 @@ static char sccsid[] = "@(#)trap.c 5.2 (Berkeley) 4/12/91";
|
||||||
#define S_DFL 1 /* default signal handling (SIG_DFL) */
|
#define S_DFL 1 /* default signal handling (SIG_DFL) */
|
||||||
#define S_CATCH 2 /* signal is caught */
|
#define S_CATCH 2 /* signal is caught */
|
||||||
#define S_IGN 3 /* signal is ignored (SIG_IGN) */
|
#define S_IGN 3 /* signal is ignored (SIG_IGN) */
|
||||||
#define S_HARD_IGN 4 /* signal is ignored permenantly */
|
#define S_HARD_IGN 4 /* signal is ignored permanently */
|
||||||
|
#define S_RESET 5 /* temporary - to reset a hard ignored sig */
|
||||||
|
|
||||||
|
|
||||||
extern char nullstr[1]; /* null string */
|
MKINIT char sigmode[_NSIG]; /* current value of signal */
|
||||||
|
|
||||||
char *trap[MAXSIG+1]; /* trap handler commands */
|
|
||||||
MKINIT char sigmode[MAXSIG]; /* current value of signal */
|
|
||||||
char gotsig[MAXSIG]; /* indicates specified signal received */
|
|
||||||
int pendingsigs; /* indicates some signal received */
|
int pendingsigs; /* indicates some signal received */
|
||||||
|
int is_interactive= -1; /* Shell is interactive */
|
||||||
|
int in_dotrap; /* do we execute in a trap handler? */
|
||||||
|
static char *volatile trap[_NSIG]; /* trap handler commands */
|
||||||
|
static volatile sig_atomic_t gotsig[_NSIG];
|
||||||
|
/* indicates specified signal received */
|
||||||
|
static int ignore_sigchld; /* Used while handling SIGCHLD traps. */
|
||||||
|
volatile sig_atomic_t gotwinch;
|
||||||
|
|
||||||
|
static int sigstring_to_signum (char *);
|
||||||
|
static void printsignals (void);
|
||||||
|
static int getsigaction(int, sig_T *);
|
||||||
|
static void onsig (int);
|
||||||
|
#ifdef NO_SIGINTERRUPT
|
||||||
|
static int siginterrupt (int,int);
|
||||||
|
#endif
|
||||||
|
static char *strsigname (int);
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Map a string to a signal number.
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
sigstring_to_signum(char *sig)
|
||||||
|
{
|
||||||
|
|
||||||
|
if (is_number(sig)) {
|
||||||
|
int signo;
|
||||||
|
|
||||||
|
signo = atoi(sig);
|
||||||
|
return ((signo >= 0 && signo < _NSIG) ? signo : (-1));
|
||||||
|
} else if (strcasecmp(sig, "exit") == 0) {
|
||||||
|
return (0);
|
||||||
|
} else {
|
||||||
|
int n;
|
||||||
|
|
||||||
|
if (strncasecmp(sig, "sig", 3) == 0)
|
||||||
|
sig += 3;
|
||||||
|
for (n = 1; n < _NSIG; n++)
|
||||||
|
if (strcasecmp(strsigname(n), sig) == 0)
|
||||||
|
return (n);
|
||||||
|
}
|
||||||
|
return (-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Print a list of valid signal names.
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
printsignals(void)
|
||||||
|
{
|
||||||
|
int n, outlen;
|
||||||
|
|
||||||
|
outlen = 0;
|
||||||
|
for (n = 1; n < _NSIG; n++) {
|
||||||
|
if (strsigname(n)) {
|
||||||
|
out1fmt("%s", strsigname(n));
|
||||||
|
outlen += strlen(strsigname(n));
|
||||||
|
} else {
|
||||||
|
out1fmt("%d", n);
|
||||||
|
outlen += 3; /* good enough */
|
||||||
|
}
|
||||||
|
++outlen;
|
||||||
|
if (outlen > 70 || n == _NSIG - 1) {
|
||||||
|
out1str("\n");
|
||||||
|
outlen = 0;
|
||||||
|
} else {
|
||||||
|
out1c(' ');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The trap builtin.
|
* The trap builtin.
|
||||||
*/
|
*/
|
||||||
|
int
|
||||||
trapcmd(argc, argv) char **argv; {
|
trapcmd(int argc, char **argv)
|
||||||
|
{
|
||||||
char *action;
|
char *action;
|
||||||
char **ap;
|
|
||||||
int signo;
|
int signo;
|
||||||
|
|
||||||
if (argc <= 1) {
|
if (argc <= 1) {
|
||||||
for (signo = 0 ; signo <= MAXSIG ; signo++) {
|
for (signo = 0 ; signo < _NSIG ; signo++) {
|
||||||
if (trap[signo] != NULL)
|
if (trap[signo] != NULL) {
|
||||||
out1fmt("%d: %s\n", signo, trap[signo]);
|
if (signo == 0) {
|
||||||
|
out1fmt("trap -- '%s' %s\n",
|
||||||
|
trap[signo], "exit");
|
||||||
|
} else if (strsigname(signo)) {
|
||||||
|
out1fmt("trap -- '%s' %s\n",
|
||||||
|
trap[signo], strsigname(signo));
|
||||||
|
} else {
|
||||||
|
out1fmt("trap -- '%s' %d\n",
|
||||||
|
trap[signo], signo);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
ap = argv + 1;
|
|
||||||
if (is_number(*ap))
|
|
||||||
action = NULL;
|
action = NULL;
|
||||||
else
|
if (*++argv && strcmp(*argv, "--") == 0)
|
||||||
action = *ap++;
|
argv++;
|
||||||
while (*ap) {
|
if (*argv && sigstring_to_signum(*argv) == -1) {
|
||||||
if ((signo = number(*ap)) < 0 || signo > MAXSIG)
|
if ((*argv)[0] != '-') {
|
||||||
error("%s: bad trap", *ap);
|
action = *argv;
|
||||||
|
argv++;
|
||||||
|
} else if ((*argv)[1] == '\0') {
|
||||||
|
argv++;
|
||||||
|
} else if ((*argv)[1] == 'l' && (*argv)[2] == '\0') {
|
||||||
|
printsignals();
|
||||||
|
return 0;
|
||||||
|
} else {
|
||||||
|
error("bad option %s", *argv);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
while (*argv) {
|
||||||
|
if ((signo = sigstring_to_signum(*argv)) == -1)
|
||||||
|
error("bad signal %s", *argv);
|
||||||
INTOFF;
|
INTOFF;
|
||||||
if (action)
|
if (action)
|
||||||
action = savestr(action);
|
action = savestr(action);
|
||||||
|
@ -107,22 +213,21 @@ trapcmd(argc, argv) char **argv; {
|
||||||
if (signo != 0)
|
if (signo != 0)
|
||||||
setsignal(signo);
|
setsignal(signo);
|
||||||
INTON;
|
INTON;
|
||||||
ap++;
|
argv++;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Clear traps on a fork.
|
* Clear traps on a fork.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void
|
void
|
||||||
clear_traps() {
|
clear_traps(void)
|
||||||
char **tp;
|
{
|
||||||
|
char *volatile *tp;
|
||||||
|
|
||||||
for (tp = trap ; tp <= &trap[MAXSIG] ; tp++) {
|
for (tp = trap ; tp <= &trap[_NSIG - 1] ; tp++) {
|
||||||
if (*tp && **tp) { /* trap not NULL or SIG_IGN */
|
if (*tp && **tp) { /* trap not NULL or SIG_IGN */
|
||||||
INTOFF;
|
INTOFF;
|
||||||
ckfree(*tp);
|
ckfree(*tp);
|
||||||
|
@ -135,18 +240,16 @@ clear_traps() {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Set the signal handler for the specified signal. The routine figures
|
* Set the signal handler for the specified signal. The routine figures
|
||||||
* out what it should be set to.
|
* out what it should be set to.
|
||||||
*/
|
*/
|
||||||
|
void
|
||||||
int
|
setsignal(int signo)
|
||||||
setsignal(signo) {
|
{
|
||||||
int action;
|
int action;
|
||||||
sig_t sigact;
|
sig_T sig, sigact = SIG_DFL;
|
||||||
char *t;
|
char *t;
|
||||||
extern void onsig();
|
|
||||||
|
|
||||||
if ((t = trap[signo]) == NULL)
|
if ((t = trap[signo]) == NULL)
|
||||||
action = S_DFL;
|
action = S_DFL;
|
||||||
|
@ -154,10 +257,9 @@ setsignal(signo) {
|
||||||
action = S_CATCH;
|
action = S_CATCH;
|
||||||
else
|
else
|
||||||
action = S_IGN;
|
action = S_IGN;
|
||||||
if (rootshell && action == S_DFL) {
|
if (action == S_DFL) {
|
||||||
switch (signo) {
|
switch (signo) {
|
||||||
case SIGINT:
|
case SIGINT:
|
||||||
if (iflag)
|
|
||||||
action = S_CATCH;
|
action = S_CATCH;
|
||||||
break;
|
break;
|
||||||
case SIGQUIT:
|
case SIGQUIT:
|
||||||
|
@ -169,68 +271,103 @@ setsignal(signo) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
/* FALLTHROUGH */
|
action = S_CATCH;
|
||||||
|
break;
|
||||||
case SIGTERM:
|
case SIGTERM:
|
||||||
if (iflag)
|
if (rootshell && iflag)
|
||||||
action = S_IGN;
|
action = S_IGN;
|
||||||
break;
|
break;
|
||||||
#if JOBS
|
#if JOBS
|
||||||
case SIGTSTP:
|
case SIGTSTP:
|
||||||
case SIGTTOU:
|
case SIGTTOU:
|
||||||
if (jflag)
|
if (rootshell && mflag)
|
||||||
action = S_IGN;
|
action = S_IGN;
|
||||||
break;
|
break;
|
||||||
|
#endif
|
||||||
|
#ifndef NO_HISTORY
|
||||||
|
case SIGWINCH:
|
||||||
|
if (rootshell && iflag)
|
||||||
|
action = S_CATCH;
|
||||||
|
break;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
t = &sigmode[signo - 1];
|
|
||||||
if (*t == 0) { /* current setting unknown */
|
t = &sigmode[signo];
|
||||||
|
if (*t == 0) {
|
||||||
/*
|
/*
|
||||||
* There is a race condition here if action is not S_IGN.
|
* current setting unknown
|
||||||
* A signal can be ignored that shouldn't be.
|
|
||||||
*/
|
*/
|
||||||
if ((int)(sigact = signal(signo, SIG_IGN)) == -1)
|
if (!getsigaction(signo, &sigact)) {
|
||||||
error("Signal system call failed");
|
/*
|
||||||
|
* Pretend it worked; maybe we should give a warning
|
||||||
|
* here, but other shells don't. We don't alter
|
||||||
|
* sigmode, so that we retry every time.
|
||||||
|
*/
|
||||||
|
return;
|
||||||
|
}
|
||||||
if (sigact == SIG_IGN) {
|
if (sigact == SIG_IGN) {
|
||||||
|
if (mflag && (signo == SIGTSTP ||
|
||||||
|
signo == SIGTTIN || signo == SIGTTOU)) {
|
||||||
|
*t = S_IGN; /* don't hard ignore these */
|
||||||
|
} else
|
||||||
*t = S_HARD_IGN;
|
*t = S_HARD_IGN;
|
||||||
} else {
|
} else {
|
||||||
*t = S_IGN;
|
*t = S_RESET; /* force to be set */
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (*t == S_HARD_IGN || *t == action)
|
if (*t == S_HARD_IGN || *t == action)
|
||||||
return 0;
|
return;
|
||||||
switch (action) {
|
switch (action) {
|
||||||
case S_DFL: sigact = SIG_DFL; break;
|
case S_DFL: sigact = SIG_DFL; break;
|
||||||
case S_CATCH: sigact = onsig; break;
|
case S_CATCH: sigact = onsig; break;
|
||||||
case S_IGN: sigact = SIG_IGN; break;
|
case S_IGN: sigact = SIG_IGN; break;
|
||||||
}
|
}
|
||||||
*t = action;
|
*t = action;
|
||||||
return (int)signal(signo, sigact);
|
sig = signal(signo, sigact);
|
||||||
|
if (sig != SIG_ERR && action == S_CATCH)
|
||||||
|
siginterrupt(signo, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Return the current setting for sig w/o changing it.
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
getsigaction(int signo, sig_T *sigact)
|
||||||
|
{
|
||||||
|
struct sigaction sa;
|
||||||
|
|
||||||
|
if (sigaction(signo, (struct sigaction *)0, &sa) == -1)
|
||||||
|
return 0;
|
||||||
|
*sigact = (sig_T) sa.sa_handler;
|
||||||
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Ignore a signal.
|
* Ignore a signal.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void
|
void
|
||||||
ignoresig(signo) {
|
ignoresig(int signo)
|
||||||
if (sigmode[signo - 1] != S_IGN && sigmode[signo - 1] != S_HARD_IGN) {
|
{
|
||||||
|
|
||||||
|
if (sigmode[signo] != S_IGN && sigmode[signo] != S_HARD_IGN) {
|
||||||
signal(signo, SIG_IGN);
|
signal(signo, SIG_IGN);
|
||||||
}
|
}
|
||||||
sigmode[signo - 1] = S_HARD_IGN;
|
sigmode[signo] = S_HARD_IGN;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#ifdef mkinit
|
#ifdef mkinit
|
||||||
INCLUDE "signames.h"
|
INCLUDE <signal.h>
|
||||||
INCLUDE "trap.h"
|
INCLUDE "trap.h"
|
||||||
|
|
||||||
SHELLPROC {
|
SHELLPROC {
|
||||||
char *sm;
|
char *sm;
|
||||||
|
|
||||||
clear_traps();
|
clear_traps();
|
||||||
for (sm = sigmode ; sm < sigmode + MAXSIG ; sm++) {
|
for (sm = sigmode ; sm < sigmode + _NSIG ; sm++) {
|
||||||
if (*sm == S_IGN)
|
if (*sm == S_IGN)
|
||||||
*sm = S_HARD_IGN;
|
*sm = S_HARD_IGN;
|
||||||
}
|
}
|
||||||
|
@ -238,82 +375,119 @@ SHELLPROC {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Signal handler.
|
* Signal handler.
|
||||||
*/
|
*/
|
||||||
|
static void
|
||||||
|
onsig(int signo)
|
||||||
|
{
|
||||||
|
|
||||||
void
|
#ifndef BSD
|
||||||
onsig(signo) {
|
|
||||||
signal(signo, onsig);
|
signal(signo, onsig);
|
||||||
|
#endif
|
||||||
if (signo == SIGINT && trap[SIGINT] == NULL) {
|
if (signo == SIGINT && trap[SIGINT] == NULL) {
|
||||||
onint();
|
onint();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
gotsig[signo - 1] = 1;
|
|
||||||
pendingsigs++;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
if (signo != SIGCHLD || !ignore_sigchld)
|
||||||
|
gotsig[signo] = 1;
|
||||||
|
pendingsigs++;
|
||||||
|
|
||||||
|
/* If we are currently in a wait builtin, prepare to break it */
|
||||||
|
if ((signo == SIGINT || signo == SIGQUIT) && in_waitcmd != 0)
|
||||||
|
breakwaitcmd = 1;
|
||||||
|
/*
|
||||||
|
* If a trap is set, not ignored and not the null command, we need
|
||||||
|
* to make sure traps are executed even when a child blocks signals.
|
||||||
|
*/
|
||||||
|
if (Tflag &&
|
||||||
|
trap[signo] != NULL &&
|
||||||
|
! trap[signo][0] == '\0' &&
|
||||||
|
! (trap[signo][0] == ':' && trap[signo][1] == '\0'))
|
||||||
|
breakwaitcmd = 1;
|
||||||
|
|
||||||
|
#ifndef NO_HISTORY
|
||||||
|
if (signo == SIGWINCH)
|
||||||
|
gotwinch = 1;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Called to execute a trap. Perhaps we should avoid entering new trap
|
* Called to execute a trap. Perhaps we should avoid entering new trap
|
||||||
* handlers while we are executing a trap handler.
|
* handlers while we are executing a trap handler.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void
|
void
|
||||||
dotrap() {
|
dotrap(void)
|
||||||
|
{
|
||||||
int i;
|
int i;
|
||||||
int savestatus;
|
int savestatus;
|
||||||
|
|
||||||
|
in_dotrap++;
|
||||||
for (;;) {
|
for (;;) {
|
||||||
for (i = 1 ; ; i++) {
|
for (i = 1; i < _NSIG; i++) {
|
||||||
if (gotsig[i - 1])
|
if (gotsig[i]) {
|
||||||
break;
|
gotsig[i] = 0;
|
||||||
if (i >= MAXSIG)
|
if (trap[i]) {
|
||||||
goto done;
|
/*
|
||||||
}
|
* Ignore SIGCHLD to avoid infinite
|
||||||
gotsig[i - 1] = 0;
|
* recursion if the trap action does
|
||||||
|
* a fork.
|
||||||
|
*/
|
||||||
|
if (i == SIGCHLD)
|
||||||
|
ignore_sigchld++;
|
||||||
savestatus = exitstatus;
|
savestatus = exitstatus;
|
||||||
evalstring(trap[i]);
|
evalstring(trap[i]);
|
||||||
exitstatus = savestatus;
|
exitstatus = savestatus;
|
||||||
|
if (i == SIGCHLD)
|
||||||
|
ignore_sigchld--;
|
||||||
}
|
}
|
||||||
done:
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (i >= _NSIG)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
in_dotrap--;
|
||||||
pendingsigs = 0;
|
pendingsigs = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Controls whether the shell is interactive or not.
|
* Controls whether the shell is interactive or not.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int is_interactive;
|
|
||||||
|
|
||||||
void
|
void
|
||||||
setinteractive(on) {
|
setinteractive(int on)
|
||||||
|
{
|
||||||
if (on == is_interactive)
|
if (on == is_interactive)
|
||||||
return;
|
return;
|
||||||
setsignal(SIGINT);
|
setsignal(SIGINT);
|
||||||
setsignal(SIGQUIT);
|
setsignal(SIGQUIT);
|
||||||
setsignal(SIGTERM);
|
setsignal(SIGTERM);
|
||||||
|
#ifndef NO_HISTORY
|
||||||
|
setsignal(SIGWINCH);
|
||||||
|
#endif
|
||||||
is_interactive = on;
|
is_interactive = on;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Called to exit the shell.
|
* Called to exit the shell.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void
|
void
|
||||||
exitshell(status) {
|
exitshell(int status)
|
||||||
|
{
|
||||||
struct jmploc loc1, loc2;
|
struct jmploc loc1, loc2;
|
||||||
char *p;
|
char *p;
|
||||||
|
|
||||||
TRACE(("exitshell(%d) pid=%d\n", status, getpid()));
|
TRACE(("exitshell(%d) pid=%d\n", status, getpid()));
|
||||||
if (setjmp(loc1.loc)) goto l1;
|
if (setjmp(loc1.loc)) {
|
||||||
if (setjmp(loc2.loc)) goto l2;
|
goto l1;
|
||||||
|
}
|
||||||
|
if (setjmp(loc2.loc)) {
|
||||||
|
goto l2;
|
||||||
|
}
|
||||||
handler = &loc1;
|
handler = &loc1;
|
||||||
if ((p = trap[0]) != NULL && *p != '\0') {
|
if ((p = trap[0]) != NULL && *p != '\0') {
|
||||||
trap[0] = NULL;
|
trap[0] = NULL;
|
||||||
|
@ -326,3 +500,85 @@ l1: handler = &loc2; /* probably unnecessary */
|
||||||
#endif
|
#endif
|
||||||
l2: _exit(status);
|
l2: _exit(status);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef NO_SIGINTERRUPT
|
||||||
|
static int siginterrupt(sig, flag)
|
||||||
|
int sig;
|
||||||
|
int flag;
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef NO_SYS_SIGNAME
|
||||||
|
static char *strsigname(sig)
|
||||||
|
int sig;
|
||||||
|
{
|
||||||
|
switch(sig)
|
||||||
|
{
|
||||||
|
case 0: return "Signal 0"; /* 0 */
|
||||||
|
case SIGHUP: return "hup"; /* 1 */
|
||||||
|
case SIGINT: return "int"; /* 2 */
|
||||||
|
case SIGQUIT: return "quit"; /* 3 */
|
||||||
|
case SIGILL: return "ill"; /* 4 */
|
||||||
|
case SIGTRAP: return "trap"; /* 5 */
|
||||||
|
case SIGABRT: return "abrt"; /* 6 */
|
||||||
|
#ifdef __minix_vmd
|
||||||
|
case SIGEMT: return "emt"; /* 7 */
|
||||||
|
#else
|
||||||
|
case SIGBUS: return "bus"; /* 7 */
|
||||||
|
#endif
|
||||||
|
case SIGFPE: return "fpe"; /* 8 */
|
||||||
|
case SIGKILL: return "kill"; /* 9 */
|
||||||
|
case SIGUSR1: return "usr1"; /* 10 */
|
||||||
|
case SIGSEGV: return "segv"; /* 11 */
|
||||||
|
case SIGUSR2: return "usr2"; /* 12 */
|
||||||
|
case SIGPIPE: return "pipe"; /* 13 */
|
||||||
|
case SIGALRM: return "alrm"; /* 14 */
|
||||||
|
case SIGTERM: return "term"; /* 15 */
|
||||||
|
#ifdef __minix_vmd
|
||||||
|
case 16: return "Signal 16"; /* 16 */
|
||||||
|
#else
|
||||||
|
case SIGEMT: return "emt"; /* 16 */
|
||||||
|
#endif
|
||||||
|
case SIGCHLD: return "chld"; /* 17 */
|
||||||
|
case SIGCONT: return "cont"; /* 18 */
|
||||||
|
case SIGSTOP: return "stop"; /* 19 */
|
||||||
|
case SIGTSTP: return "tstp"; /* 20 */
|
||||||
|
case SIGTTIN: return "ttin"; /* 21 */
|
||||||
|
case SIGTTOU: return "ttou"; /* 22 */
|
||||||
|
case SIGWINCH: return "winch"; /* 23 */
|
||||||
|
#ifdef __minix_vmd
|
||||||
|
case SIGFPEMU: return "fpemu"; /* 30 */
|
||||||
|
#endif
|
||||||
|
default: return "Signal n";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
static char *strsigname(sig)
|
||||||
|
int sig;
|
||||||
|
{
|
||||||
|
return sys_signame[sig];
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef NO_SYS_SIGLIST
|
||||||
|
#include "signames.h"
|
||||||
|
char *strsiglist(sig)
|
||||||
|
int sig;
|
||||||
|
{
|
||||||
|
if (sig > MAXSIG)
|
||||||
|
return NULL;
|
||||||
|
return sigmesg[sig];
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
char *strsiglist(sig)
|
||||||
|
int sig;
|
||||||
|
{
|
||||||
|
return sys_siglist[sig];
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
* $PchId: trap.c,v 1.7 2006/05/23 11:56:21 philip Exp $
|
||||||
|
*/
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/*-
|
/*-
|
||||||
* Copyright (c) 1991 The Regents of the University of California.
|
* Copyright (c) 1991, 1993
|
||||||
* All rights reserved.
|
* The Regents of the University of California. All rights reserved.
|
||||||
*
|
*
|
||||||
* This code is derived from software contributed to Berkeley by
|
* This code is derived from software contributed to Berkeley by
|
||||||
* Kenneth Almquist.
|
* Kenneth Almquist.
|
||||||
|
@ -13,10 +13,6 @@
|
||||||
* 2. Redistributions in binary form must reproduce the above copyright
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
* notice, this list of conditions and the following disclaimer in the
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
* documentation and/or other materials provided with the distribution.
|
* documentation and/or other materials provided with the distribution.
|
||||||
* 3. All advertising materials mentioning features or use of this software
|
|
||||||
* must display the following acknowledgement:
|
|
||||||
* This product includes software developed by the University of
|
|
||||||
* California, Berkeley and its contributors.
|
|
||||||
* 4. Neither the name of the University nor the names of its contributors
|
* 4. Neither the name of the University nor the names of its contributors
|
||||||
* may be used to endorse or promote products derived from this software
|
* may be used to endorse or promote products derived from this software
|
||||||
* without specific prior written permission.
|
* without specific prior written permission.
|
||||||
|
@ -33,23 +29,24 @@
|
||||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||||
* SUCH DAMAGE.
|
* SUCH DAMAGE.
|
||||||
*
|
*
|
||||||
* @(#)trap.h 5.1 (Berkeley) 3/7/91
|
* @(#)trap.h 8.3 (Berkeley) 6/5/95
|
||||||
|
* $FreeBSD: src/bin/sh/trap.h,v 1.12 2004/04/06 20:06:51 markm Exp $
|
||||||
*/
|
*/
|
||||||
|
|
||||||
extern int pendingsigs;
|
extern int pendingsigs;
|
||||||
|
extern int in_dotrap;
|
||||||
|
extern int is_interactive;
|
||||||
|
extern volatile sig_atomic_t gotwinch;
|
||||||
|
|
||||||
#ifdef __STDC__
|
int trapcmd(int, char **);
|
||||||
void clear_traps(void);
|
void clear_traps(void);
|
||||||
int setsignal(int);
|
void setsignal(int);
|
||||||
void ignoresig(int);
|
void ignoresig(int);
|
||||||
void dotrap(void);
|
void dotrap(void);
|
||||||
void setinteractive(int);
|
void setinteractive(int);
|
||||||
void exitshell(int);
|
void exitshell(int);
|
||||||
#else
|
char *strsiglist(int);
|
||||||
void clear_traps();
|
|
||||||
int setsignal();
|
/*
|
||||||
void ignoresig();
|
* $PchId: trap.h,v 1.6 2006/05/22 12:48:30 philip Exp $
|
||||||
void dotrap();
|
*/
|
||||||
void setinteractive();
|
|
||||||
void exitshell();
|
|
||||||
#endif
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/*-
|
/*-
|
||||||
* Copyright (c) 1991 The Regents of the University of California.
|
* Copyright (c) 1991, 1993
|
||||||
* All rights reserved.
|
* The Regents of the University of California. All rights reserved.
|
||||||
*
|
*
|
||||||
* This code is derived from software contributed to Berkeley by
|
* This code is derived from software contributed to Berkeley by
|
||||||
* Kenneth Almquist.
|
* Kenneth Almquist.
|
||||||
|
@ -13,10 +13,6 @@
|
||||||
* 2. Redistributions in binary form must reproduce the above copyright
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
* notice, this list of conditions and the following disclaimer in the
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
* documentation and/or other materials provided with the distribution.
|
* documentation and/or other materials provided with the distribution.
|
||||||
* 3. All advertising materials mentioning features or use of this software
|
|
||||||
* must display the following acknowledgement:
|
|
||||||
* This product includes software developed by the University of
|
|
||||||
* California, Berkeley and its contributors.
|
|
||||||
* 4. Neither the name of the University nor the names of its contributors
|
* 4. Neither the name of the University nor the names of its contributors
|
||||||
* may be used to endorse or promote products derived from this software
|
* may be used to endorse or promote products derived from this software
|
||||||
* without specific prior written permission.
|
* without specific prior written permission.
|
||||||
|
@ -35,13 +31,27 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef lint
|
#ifndef lint
|
||||||
static char sccsid[] = "@(#)var.c 5.3 (Berkeley) 4/12/91";
|
#if 0
|
||||||
|
static char sccsid[] = "@(#)var.c 8.3 (Berkeley) 5/4/95";
|
||||||
|
#endif
|
||||||
#endif /* not lint */
|
#endif /* not lint */
|
||||||
|
/*
|
||||||
|
#include <sys/cdefs.h>
|
||||||
|
__FBSDID("$FreeBSD: src/bin/sh/var.c,v 1.26.2.1 2004/09/30 04:41:55 des Exp $");
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#ifndef NO_PATHS_H
|
||||||
|
#include <paths.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Shell variables.
|
* Shell variables.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <locale.h>
|
||||||
|
|
||||||
#include "shell.h"
|
#include "shell.h"
|
||||||
#include "output.h"
|
#include "output.h"
|
||||||
#include "expand.h"
|
#include "expand.h"
|
||||||
|
@ -55,7 +65,16 @@ static char sccsid[] = "@(#)var.c 5.3 (Berkeley) 4/12/91";
|
||||||
#include "memalloc.h"
|
#include "memalloc.h"
|
||||||
#include "error.h"
|
#include "error.h"
|
||||||
#include "mystring.h"
|
#include "mystring.h"
|
||||||
|
#include "parser.h"
|
||||||
|
#if !defined(NO_HISTORY) && !defined(EDITLINE)
|
||||||
|
#include "myhistedit.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "builtins.h"
|
||||||
|
|
||||||
|
#ifndef _PATH_DEFPATH
|
||||||
|
#define _PATH_DEFPATH "/usr/bin:/bin"
|
||||||
|
#endif
|
||||||
|
|
||||||
#define VTABSIZE 39
|
#define VTABSIZE 39
|
||||||
|
|
||||||
|
@ -64,48 +83,57 @@ struct varinit {
|
||||||
struct var *var;
|
struct var *var;
|
||||||
int flags;
|
int flags;
|
||||||
char *text;
|
char *text;
|
||||||
|
void (*func)(const char *);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
#if ATTY
|
#ifndef NO_HISTORY
|
||||||
struct var vatty;
|
struct var vhistsize;
|
||||||
#endif
|
#endif
|
||||||
struct var vifs;
|
struct var vifs;
|
||||||
struct var vmail;
|
struct var vmail;
|
||||||
struct var vmpath;
|
struct var vmpath;
|
||||||
struct var vpath;
|
struct var vpath;
|
||||||
|
struct var vppid;
|
||||||
struct var vps1;
|
struct var vps1;
|
||||||
struct var vps2;
|
struct var vps2;
|
||||||
struct var vpse;
|
struct var vpse;
|
||||||
struct var vvers;
|
struct var vvers;
|
||||||
#if ATTY
|
STATIC struct var voptind;
|
||||||
struct var vterm;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
const struct varinit varinit[] = {
|
STATIC const struct varinit varinit[] = {
|
||||||
#if ATTY
|
#if !defined(NO_HISTORY) && !defined(EDITLINE)
|
||||||
{&vatty, VSTRFIXED|VTEXTFIXED|VUNSET, "ATTY="},
|
{ &vhistsize, VSTRFIXED|VTEXTFIXED|VUNSET, "HISTSIZE=",
|
||||||
|
sethistsize },
|
||||||
#endif
|
#endif
|
||||||
{&vifs, VSTRFIXED|VTEXTFIXED, "IFS= \t\n"},
|
{ &vifs, VSTRFIXED|VTEXTFIXED, "IFS= \t\n",
|
||||||
{&vmail, VSTRFIXED|VTEXTFIXED|VUNSET, "MAIL="},
|
NULL },
|
||||||
{&vmpath, VSTRFIXED|VTEXTFIXED|VUNSET, "MAILPATH="},
|
{ &vmail, VSTRFIXED|VTEXTFIXED|VUNSET, "MAIL=",
|
||||||
{&vpath, VSTRFIXED|VTEXTFIXED, "PATH=:/bin:/usr/bin"},
|
NULL },
|
||||||
|
{ &vmpath, VSTRFIXED|VTEXTFIXED|VUNSET, "MAILPATH=",
|
||||||
|
NULL },
|
||||||
|
{ &vpath, VSTRFIXED|VTEXTFIXED, "PATH=" _PATH_DEFPATH,
|
||||||
|
changepath },
|
||||||
|
{ &vppid, VSTRFIXED|VTEXTFIXED|VUNSET, "PPID=",
|
||||||
|
NULL },
|
||||||
/*
|
/*
|
||||||
* vps1 depends on uid
|
* vps1 depends on uid
|
||||||
*/
|
*/
|
||||||
{&vps2, VSTRFIXED|VTEXTFIXED, "PS2=> "},
|
{ &vps2, VSTRFIXED|VTEXTFIXED, "PS2=> ",
|
||||||
{&vpse, VSTRFIXED|VTEXTFIXED, "PSE=* "},
|
NULL },
|
||||||
#if ATTY
|
{ &vpse, VSTRFIXED|VTEXTFIXED|VUNSET, "PSE=",
|
||||||
{&vterm, VSTRFIXED|VTEXTFIXED|VUNSET, "TERM="},
|
NULL },
|
||||||
#endif
|
{ &voptind, VSTRFIXED|VTEXTFIXED, "OPTIND=1",
|
||||||
{NULL, 0, NULL}
|
getoptsreset },
|
||||||
|
{ NULL, 0, NULL,
|
||||||
|
NULL }
|
||||||
};
|
};
|
||||||
|
|
||||||
struct var *vartab[VTABSIZE];
|
STATIC struct var *vartab[VTABSIZE];
|
||||||
|
|
||||||
STATIC void unsetvar __P((char *));
|
STATIC struct var **hashvar(char *);
|
||||||
STATIC struct var **hashvar __P((char *));
|
STATIC int varequal(char *, char *);
|
||||||
STATIC int varequal __P((char *, char *));
|
STATIC int localevar(char *);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Initialize the varable symbol tables and import the environment
|
* Initialize the varable symbol tables and import the environment
|
||||||
|
@ -133,7 +161,9 @@ INIT {
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void
|
void
|
||||||
initvar() {
|
initvar(void)
|
||||||
|
{
|
||||||
|
char ppid[20];
|
||||||
const struct varinit *ip;
|
const struct varinit *ip;
|
||||||
struct var *vp;
|
struct var *vp;
|
||||||
struct var **vpp;
|
struct var **vpp;
|
||||||
|
@ -145,6 +175,7 @@ initvar() {
|
||||||
*vpp = vp;
|
*vpp = vp;
|
||||||
vp->text = ip->text;
|
vp->text = ip->text;
|
||||||
vp->flags = ip->flags;
|
vp->flags = ip->flags;
|
||||||
|
vp->func = ip->func;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
|
@ -154,19 +185,47 @@ initvar() {
|
||||||
vpp = hashvar("PS1=");
|
vpp = hashvar("PS1=");
|
||||||
vps1.next = *vpp;
|
vps1.next = *vpp;
|
||||||
*vpp = &vps1;
|
*vpp = &vps1;
|
||||||
vps1.text = getuid() ? "PS1=$ " : "PS1=# ";
|
vps1.text = geteuid() ? "PS1=$ " : "PS1=# ";
|
||||||
vps1.flags = VSTRFIXED|VTEXTFIXED;
|
vps1.flags = VSTRFIXED|VTEXTFIXED;
|
||||||
}
|
}
|
||||||
|
if ((vppid.flags & VEXPORT) == 0) {
|
||||||
|
fmtstr(ppid, sizeof(ppid), "%d", (int)getppid());
|
||||||
|
setvarsafe("PPID", ppid, 0);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Set the value of a variable. The flags argument is ored with the
|
* Safe version of setvar, returns 1 on success 0 on failure.
|
||||||
|
*/
|
||||||
|
|
||||||
|
int
|
||||||
|
setvarsafe(char *name, char *val, int flags)
|
||||||
|
{
|
||||||
|
struct jmploc jmploc;
|
||||||
|
struct jmploc *volatile savehandler = handler;
|
||||||
|
int err = 0;
|
||||||
|
#if __GNUC__
|
||||||
|
/* Avoid longjmp clobbering */
|
||||||
|
(void) &err;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (setjmp(jmploc.loc))
|
||||||
|
err = 1;
|
||||||
|
else {
|
||||||
|
handler = &jmploc;
|
||||||
|
setvar(name, val, flags);
|
||||||
|
}
|
||||||
|
handler = savehandler;
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Set the value of a variable. The flags argument is tored with the
|
||||||
* flags of the variable. If val is NULL, the variable is unset.
|
* flags of the variable. If val is NULL, the variable is unset.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void
|
void
|
||||||
setvar(name, val, flags)
|
setvar(char *name, char *val, int flags)
|
||||||
char *name, *val;
|
|
||||||
{
|
{
|
||||||
char *p, *q;
|
char *p, *q;
|
||||||
int len;
|
int len;
|
||||||
|
@ -176,8 +235,9 @@ setvar(name, val, flags)
|
||||||
|
|
||||||
isbad = 0;
|
isbad = 0;
|
||||||
p = name;
|
p = name;
|
||||||
if (! is_name(*p++))
|
if (! is_name(*p))
|
||||||
isbad = 1;
|
isbad = 1;
|
||||||
|
p++;
|
||||||
for (;;) {
|
for (;;) {
|
||||||
if (! is_in_name(*p)) {
|
if (! is_in_name(*p)) {
|
||||||
if (*p == '\0' || *p == '=')
|
if (*p == '\0' || *p == '=')
|
||||||
|
@ -188,7 +248,7 @@ setvar(name, val, flags)
|
||||||
}
|
}
|
||||||
namelen = p - name;
|
namelen = p - name;
|
||||||
if (isbad)
|
if (isbad)
|
||||||
error("%.*s: is read only", namelen, name);
|
error("%.*s: bad variable name", namelen, name);
|
||||||
len = namelen + 2; /* 2 is space for '=' and '\0' */
|
len = namelen + 2; /* 2 is space for '=' and '\0' */
|
||||||
if (val == NULL) {
|
if (val == NULL) {
|
||||||
flags |= VUNSET;
|
flags |= VUNSET;
|
||||||
|
@ -206,7 +266,26 @@ setvar(name, val, flags)
|
||||||
setvareq(nameeq, flags);
|
setvareq(nameeq, flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
STATIC int
|
||||||
|
localevar(char *s)
|
||||||
|
{
|
||||||
|
static char *lnames[7] = {
|
||||||
|
"ALL", "COLLATE", "CTYPE", "MONETARY",
|
||||||
|
"NUMERIC", "TIME", NULL
|
||||||
|
};
|
||||||
|
char **ss;
|
||||||
|
|
||||||
|
if (*s != 'L')
|
||||||
|
return 0;
|
||||||
|
if (varequal(s + 1, "ANG"))
|
||||||
|
return 1;
|
||||||
|
if (strncmp(s + 1, "C_", 2) != 0)
|
||||||
|
return 0;
|
||||||
|
for (ss = lnames; *ss ; ss++)
|
||||||
|
if (varequal(s + 3, *ss))
|
||||||
|
return 1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Same as setvar except that the variable and value are passed in
|
* Same as setvar except that the variable and value are passed in
|
||||||
|
@ -216,28 +295,42 @@ setvar(name, val, flags)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void
|
void
|
||||||
setvareq(s, flags)
|
setvareq(char *s, int flags)
|
||||||
char *s;
|
|
||||||
{
|
{
|
||||||
struct var *vp, **vpp;
|
struct var *vp, **vpp;
|
||||||
|
int len;
|
||||||
|
|
||||||
|
if (aflag)
|
||||||
|
flags |= VEXPORT;
|
||||||
vpp = hashvar(s);
|
vpp = hashvar(s);
|
||||||
for (vp = *vpp ; vp ; vp = vp->next) {
|
for (vp = *vpp ; vp ; vp = vp->next) {
|
||||||
if (varequal(s, vp->text)) {
|
if (varequal(s, vp->text)) {
|
||||||
if (vp->flags & VREADONLY) {
|
if (vp->flags & VREADONLY) {
|
||||||
int len = strchr(s, '=') - s;
|
len = strchr(s, '=') - s;
|
||||||
error("%.*s: is read only", len, s);
|
error("%.*s: is read only", len, s);
|
||||||
}
|
}
|
||||||
INTOFF;
|
INTOFF;
|
||||||
if (vp == &vpath)
|
|
||||||
changepath(s + 5); /* 5 = strlen("PATH=") */
|
if (vp->func && (flags & VNOFUNC) == 0)
|
||||||
|
(*vp->func)(strchr(s, '=') + 1);
|
||||||
|
|
||||||
if ((vp->flags & (VTEXTFIXED|VSTACK)) == 0)
|
if ((vp->flags & (VTEXTFIXED|VSTACK)) == 0)
|
||||||
ckfree(vp->text);
|
ckfree(vp->text);
|
||||||
|
|
||||||
vp->flags &= ~(VTEXTFIXED|VSTACK|VUNSET);
|
vp->flags &= ~(VTEXTFIXED|VSTACK|VUNSET);
|
||||||
vp->flags |= flags;
|
vp->flags |= flags;
|
||||||
vp->text = s;
|
vp->text = s;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* We could roll this to a function, to handle it as
|
||||||
|
* a regular variable function callback, but why bother?
|
||||||
|
*/
|
||||||
if (vp == &vmpath || (vp == &vmail && ! mpathset()))
|
if (vp == &vmpath || (vp == &vmail && ! mpathset()))
|
||||||
chkmail(1);
|
chkmail(1);
|
||||||
|
if ((vp->flags & VEXPORT) && localevar(s)) {
|
||||||
|
putenv(s);
|
||||||
|
(void) setlocale(LC_ALL, "");
|
||||||
|
}
|
||||||
INTON;
|
INTON;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -247,7 +340,14 @@ setvareq(s, flags)
|
||||||
vp->flags = flags;
|
vp->flags = flags;
|
||||||
vp->text = s;
|
vp->text = s;
|
||||||
vp->next = *vpp;
|
vp->next = *vpp;
|
||||||
|
vp->func = NULL;
|
||||||
|
INTOFF;
|
||||||
*vpp = vp;
|
*vpp = vp;
|
||||||
|
if ((vp->flags & VEXPORT) && localevar(s)) {
|
||||||
|
putenv(s);
|
||||||
|
(void) setlocale(LC_ALL, "");
|
||||||
|
}
|
||||||
|
INTON;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -257,8 +357,7 @@ setvareq(s, flags)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void
|
void
|
||||||
listsetvar(list)
|
listsetvar(struct strlist *list)
|
||||||
struct strlist *list;
|
|
||||||
{
|
{
|
||||||
struct strlist *lp;
|
struct strlist *lp;
|
||||||
|
|
||||||
|
@ -276,8 +375,7 @@ listsetvar(list)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
char *
|
char *
|
||||||
lookupvar(name)
|
lookupvar(char *name)
|
||||||
char *name;
|
|
||||||
{
|
{
|
||||||
struct var *v;
|
struct var *v;
|
||||||
|
|
||||||
|
@ -300,8 +398,7 @@ lookupvar(name)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
char *
|
char *
|
||||||
bltinlookup(name, doall)
|
bltinlookup(char *name, int doall)
|
||||||
char *name;
|
|
||||||
{
|
{
|
||||||
struct strlist *sp;
|
struct strlist *sp;
|
||||||
struct var *v;
|
struct var *v;
|
||||||
|
@ -312,8 +409,8 @@ bltinlookup(name, doall)
|
||||||
}
|
}
|
||||||
for (v = *hashvar(name) ; v ; v = v->next) {
|
for (v = *hashvar(name) ; v ; v = v->next) {
|
||||||
if (varequal(v->text, name)) {
|
if (varequal(v->text, name)) {
|
||||||
if (v->flags & VUNSET
|
if ((v->flags & VUNSET)
|
||||||
|| ! doall && (v->flags & VEXPORT) == 0)
|
|| (!doall && (v->flags & VEXPORT) == 0))
|
||||||
return NULL;
|
return NULL;
|
||||||
return strchr(v->text, '=') + 1;
|
return strchr(v->text, '=') + 1;
|
||||||
}
|
}
|
||||||
|
@ -329,7 +426,8 @@ bltinlookup(name, doall)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
char **
|
char **
|
||||||
environment() {
|
environment(void)
|
||||||
|
{
|
||||||
int nenv;
|
int nenv;
|
||||||
struct var **vpp;
|
struct var **vpp;
|
||||||
struct var *vp;
|
struct var *vp;
|
||||||
|
@ -359,15 +457,14 @@ environment() {
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifdef mkinit
|
#ifdef mkinit
|
||||||
MKINIT void shprocvar();
|
|
||||||
|
|
||||||
SHELLPROC {
|
SHELLPROC {
|
||||||
shprocvar();
|
shprocvar();
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
void
|
void
|
||||||
shprocvar() {
|
shprocvar(void)
|
||||||
|
{
|
||||||
struct var **vpp;
|
struct var **vpp;
|
||||||
struct var *vp, **prev;
|
struct var *vp, **prev;
|
||||||
|
|
||||||
|
@ -400,14 +497,21 @@ shprocvar() {
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int
|
int
|
||||||
showvarscmd(argc, argv) char **argv; {
|
showvarscmd(int argc __unused, char **argv __unused)
|
||||||
|
{
|
||||||
struct var **vpp;
|
struct var **vpp;
|
||||||
struct var *vp;
|
struct var *vp;
|
||||||
|
const char *s;
|
||||||
|
|
||||||
for (vpp = vartab ; vpp < vartab + VTABSIZE ; vpp++) {
|
for (vpp = vartab ; vpp < vartab + VTABSIZE ; vpp++) {
|
||||||
for (vp = *vpp ; vp ; vp = vp->next) {
|
for (vp = *vpp ; vp ; vp = vp->next) {
|
||||||
if ((vp->flags & VUNSET) == 0)
|
if (vp->flags & VUNSET)
|
||||||
out1fmt("%s\n", vp->text);
|
continue;
|
||||||
|
for (s = vp->text; *s != '='; s++)
|
||||||
|
out1c(*s);
|
||||||
|
out1c('=');
|
||||||
|
out1qstr(s + 1);
|
||||||
|
out1c('\n');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -420,15 +524,35 @@ showvarscmd(argc, argv) char **argv; {
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int
|
int
|
||||||
exportcmd(argc, argv) char **argv; {
|
exportcmd(int argc, char **argv)
|
||||||
|
{
|
||||||
struct var **vpp;
|
struct var **vpp;
|
||||||
struct var *vp;
|
struct var *vp;
|
||||||
char *name;
|
char *name;
|
||||||
char *p;
|
char *p;
|
||||||
|
char *cmdname;
|
||||||
|
int ch, values;
|
||||||
int flag = argv[0][0] == 'r'? VREADONLY : VEXPORT;
|
int flag = argv[0][0] == 'r'? VREADONLY : VEXPORT;
|
||||||
|
|
||||||
|
cmdname = argv[0];
|
||||||
|
optreset = optind = 1;
|
||||||
|
opterr = 0;
|
||||||
|
values = 0;
|
||||||
|
while ((ch = getopt(argc, argv, "p")) != -1) {
|
||||||
|
switch (ch) {
|
||||||
|
case 'p':
|
||||||
|
values = 1;
|
||||||
|
break;
|
||||||
|
case '?':
|
||||||
|
default:
|
||||||
|
error("unknown option: -%c", optopt);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
argc -= optind;
|
||||||
|
argv += optind;
|
||||||
|
|
||||||
listsetvar(cmdenviron);
|
listsetvar(cmdenviron);
|
||||||
if (argc > 1) {
|
if (argc != 0) {
|
||||||
while ((name = *argptr++) != NULL) {
|
while ((name = *argptr++) != NULL) {
|
||||||
if ((p = strchr(name, '=')) != NULL) {
|
if ((p = strchr(name, '=')) != NULL) {
|
||||||
p++;
|
p++;
|
||||||
|
@ -436,7 +560,12 @@ exportcmd(argc, argv) char **argv; {
|
||||||
vpp = hashvar(name);
|
vpp = hashvar(name);
|
||||||
for (vp = *vpp ; vp ; vp = vp->next) {
|
for (vp = *vpp ; vp ; vp = vp->next) {
|
||||||
if (varequal(vp->text, name)) {
|
if (varequal(vp->text, name)) {
|
||||||
|
|
||||||
vp->flags |= flag;
|
vp->flags |= flag;
|
||||||
|
if ((vp->flags & VEXPORT) && localevar(vp->text)) {
|
||||||
|
putenv(vp->text);
|
||||||
|
(void) setlocale(LC_ALL, "");
|
||||||
|
}
|
||||||
goto found;
|
goto found;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -448,8 +577,16 @@ found:;
|
||||||
for (vpp = vartab ; vpp < vartab + VTABSIZE ; vpp++) {
|
for (vpp = vartab ; vpp < vartab + VTABSIZE ; vpp++) {
|
||||||
for (vp = *vpp ; vp ; vp = vp->next) {
|
for (vp = *vpp ; vp ; vp = vp->next) {
|
||||||
if (vp->flags & flag) {
|
if (vp->flags & flag) {
|
||||||
|
if (values) {
|
||||||
|
out1str(cmdname);
|
||||||
|
out1c(' ');
|
||||||
|
}
|
||||||
for (p = vp->text ; *p != '=' ; p++)
|
for (p = vp->text ; *p != '=' ; p++)
|
||||||
out1c(*p);
|
out1c(*p);
|
||||||
|
if (values && !(vp->flags & VUNSET)) {
|
||||||
|
out1c('=');
|
||||||
|
out1qstr(p + 1);
|
||||||
|
}
|
||||||
out1c('\n');
|
out1c('\n');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -463,7 +600,9 @@ found:;
|
||||||
* The "local" command.
|
* The "local" command.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
localcmd(argc, argv) char **argv; {
|
int
|
||||||
|
localcmd(int argc __unused, char **argv __unused)
|
||||||
|
{
|
||||||
char *name;
|
char *name;
|
||||||
|
|
||||||
if (! in_function())
|
if (! in_function())
|
||||||
|
@ -483,8 +622,7 @@ localcmd(argc, argv) char **argv; {
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void
|
void
|
||||||
mklocal(name)
|
mklocal(char *name)
|
||||||
char *name;
|
|
||||||
{
|
{
|
||||||
struct localvar *lvp;
|
struct localvar *lvp;
|
||||||
struct var **vpp;
|
struct var **vpp;
|
||||||
|
@ -493,8 +631,8 @@ mklocal(name)
|
||||||
INTOFF;
|
INTOFF;
|
||||||
lvp = ckmalloc(sizeof (struct localvar));
|
lvp = ckmalloc(sizeof (struct localvar));
|
||||||
if (name[0] == '-' && name[1] == '\0') {
|
if (name[0] == '-' && name[1] == '\0') {
|
||||||
lvp->text = ckmalloc(sizeof optval);
|
lvp->text = ckmalloc(sizeof optlist);
|
||||||
bcopy(optval, lvp->text, sizeof optval);
|
memcpy(lvp->text, optlist, sizeof optlist);
|
||||||
vp = NULL;
|
vp = NULL;
|
||||||
} else {
|
} else {
|
||||||
vpp = hashvar(name);
|
vpp = hashvar(name);
|
||||||
|
@ -527,7 +665,8 @@ mklocal(name)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void
|
void
|
||||||
poplocalvars() {
|
poplocalvars(void)
|
||||||
|
{
|
||||||
struct localvar *lvp;
|
struct localvar *lvp;
|
||||||
struct var *vp;
|
struct var *vp;
|
||||||
|
|
||||||
|
@ -535,10 +674,10 @@ poplocalvars() {
|
||||||
localvars = lvp->next;
|
localvars = lvp->next;
|
||||||
vp = lvp->vp;
|
vp = lvp->vp;
|
||||||
if (vp == NULL) { /* $- saved */
|
if (vp == NULL) { /* $- saved */
|
||||||
bcopy(lvp->text, optval, sizeof optval);
|
memcpy(optlist, lvp->text, sizeof optlist);
|
||||||
ckfree(lvp->text);
|
ckfree(lvp->text);
|
||||||
} else if ((lvp->flags & (VUNSET|VSTRFIXED)) == VUNSET) {
|
} else if ((lvp->flags & (VUNSET|VSTRFIXED)) == VUNSET) {
|
||||||
unsetvar(vp->text);
|
(void)unsetvar(vp->text);
|
||||||
} else {
|
} else {
|
||||||
if ((vp->flags & VTEXTFIXED) == 0)
|
if ((vp->flags & VTEXTFIXED) == 0)
|
||||||
ckfree(vp->text);
|
ckfree(vp->text);
|
||||||
|
@ -550,7 +689,9 @@ poplocalvars() {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
setvarcmd(argc, argv) char **argv; {
|
int
|
||||||
|
setvarcmd(int argc, char **argv)
|
||||||
|
{
|
||||||
if (argc <= 2)
|
if (argc <= 2)
|
||||||
return unsetcmd(argc, argv);
|
return unsetcmd(argc, argv);
|
||||||
else if (argc == 3)
|
else if (argc == 3)
|
||||||
|
@ -567,14 +708,31 @@ setvarcmd(argc, argv) char **argv; {
|
||||||
* with the same name.
|
* with the same name.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
unsetcmd(argc, argv) char **argv; {
|
int
|
||||||
|
unsetcmd(int argc __unused, char **argv __unused)
|
||||||
|
{
|
||||||
char **ap;
|
char **ap;
|
||||||
|
int i;
|
||||||
|
int flg_func = 0;
|
||||||
|
int flg_var = 0;
|
||||||
|
int ret = 0;
|
||||||
|
|
||||||
for (ap = argv + 1 ; *ap ; ap++) {
|
while ((i = nextopt("vf")) != '\0') {
|
||||||
unsetfunc(*ap);
|
if (i == 'f')
|
||||||
unsetvar(*ap);
|
flg_func = 1;
|
||||||
|
else
|
||||||
|
flg_var = 1;
|
||||||
}
|
}
|
||||||
return 0;
|
if (flg_func == 0 && flg_var == 0)
|
||||||
|
flg_var = 1;
|
||||||
|
|
||||||
|
for (ap = argptr; *ap ; ap++) {
|
||||||
|
if (flg_func)
|
||||||
|
ret |= unsetfunc(*ap);
|
||||||
|
if (flg_var)
|
||||||
|
ret |= unsetvar(*ap);
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -582,9 +740,8 @@ unsetcmd(argc, argv) char **argv; {
|
||||||
* Unset the specified variable.
|
* Unset the specified variable.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
STATIC void
|
int
|
||||||
unsetvar(s)
|
unsetvar(char *s)
|
||||||
char *s;
|
|
||||||
{
|
{
|
||||||
struct var **vpp;
|
struct var **vpp;
|
||||||
struct var *vp;
|
struct var *vp;
|
||||||
|
@ -592,10 +749,14 @@ unsetvar(s)
|
||||||
vpp = hashvar(s);
|
vpp = hashvar(s);
|
||||||
for (vp = *vpp ; vp ; vpp = &vp->next, vp = *vpp) {
|
for (vp = *vpp ; vp ; vpp = &vp->next, vp = *vpp) {
|
||||||
if (varequal(vp->text, s)) {
|
if (varequal(vp->text, s)) {
|
||||||
|
if (vp->flags & VREADONLY)
|
||||||
|
return (1);
|
||||||
INTOFF;
|
INTOFF;
|
||||||
if (*(strchr(vp->text, '=') + 1) != '\0'
|
if (*(strchr(vp->text, '=') + 1) != '\0')
|
||||||
|| vp->flags & VREADONLY) {
|
|
||||||
setvar(s, nullstr, 0);
|
setvar(s, nullstr, 0);
|
||||||
|
if ((vp->flags & VEXPORT) && localevar(vp->text)) {
|
||||||
|
unsetenv(s);
|
||||||
|
setlocale(LC_ALL, "");
|
||||||
}
|
}
|
||||||
vp->flags &= ~VEXPORT;
|
vp->flags &= ~VEXPORT;
|
||||||
vp->flags |= VUNSET;
|
vp->flags |= VUNSET;
|
||||||
|
@ -606,9 +767,11 @@ unsetvar(s)
|
||||||
ckfree(vp);
|
ckfree(vp);
|
||||||
}
|
}
|
||||||
INTON;
|
INTON;
|
||||||
return;
|
return (0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return (0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -618,14 +781,13 @@ unsetvar(s)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
STATIC struct var **
|
STATIC struct var **
|
||||||
hashvar(p)
|
hashvar(char *p)
|
||||||
register char *p;
|
|
||||||
{
|
{
|
||||||
unsigned int hashval;
|
unsigned int hashval;
|
||||||
|
|
||||||
hashval = *p << 4;
|
hashval = ((unsigned char) *p) << 4;
|
||||||
while (*p && *p != '=')
|
while (*p && *p != '=')
|
||||||
hashval += *p++;
|
hashval += (unsigned char) *p++;
|
||||||
return &vartab[hashval % VTABSIZE];
|
return &vartab[hashval % VTABSIZE];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -638,8 +800,7 @@ hashvar(p)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
STATIC int
|
STATIC int
|
||||||
varequal(p, q)
|
varequal(char *p, char *q)
|
||||||
register char *p, *q;
|
|
||||||
{
|
{
|
||||||
while (*p == *q++) {
|
while (*p == *q++) {
|
||||||
if (*p++ == '=')
|
if (*p++ == '=')
|
||||||
|
@ -649,3 +810,7 @@ varequal(p, q)
|
||||||
return 1;
|
return 1;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* $PchId: var.c,v 1.5 2006/05/22 12:28:49 philip Exp $
|
||||||
|
*/
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/*-
|
/*-
|
||||||
* Copyright (c) 1991 The Regents of the University of California.
|
* Copyright (c) 1991, 1993
|
||||||
* All rights reserved.
|
* The Regents of the University of California. All rights reserved.
|
||||||
*
|
*
|
||||||
* This code is derived from software contributed to Berkeley by
|
* This code is derived from software contributed to Berkeley by
|
||||||
* Kenneth Almquist.
|
* Kenneth Almquist.
|
||||||
|
@ -13,10 +13,6 @@
|
||||||
* 2. Redistributions in binary form must reproduce the above copyright
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
* notice, this list of conditions and the following disclaimer in the
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
* documentation and/or other materials provided with the distribution.
|
* documentation and/or other materials provided with the distribution.
|
||||||
* 3. All advertising materials mentioning features or use of this software
|
|
||||||
* must display the following acknowledgement:
|
|
||||||
* This product includes software developed by the University of
|
|
||||||
* California, Berkeley and its contributors.
|
|
||||||
* 4. Neither the name of the University nor the names of its contributors
|
* 4. Neither the name of the University nor the names of its contributors
|
||||||
* may be used to endorse or promote products derived from this software
|
* may be used to endorse or promote products derived from this software
|
||||||
* without specific prior written permission.
|
* without specific prior written permission.
|
||||||
|
@ -33,7 +29,8 @@
|
||||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||||
* SUCH DAMAGE.
|
* SUCH DAMAGE.
|
||||||
*
|
*
|
||||||
* @(#)var.h 5.1 (Berkeley) 3/7/91
|
* @(#)var.h 8.2 (Berkeley) 5/4/95
|
||||||
|
* $FreeBSD: src/bin/sh/var.h,v 1.12 2004/04/06 20:06:51 markm Exp $
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -41,18 +38,22 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* flags */
|
/* flags */
|
||||||
#define VEXPORT 01 /* variable is exported */
|
#define VEXPORT 0x01 /* variable is exported */
|
||||||
#define VREADONLY 02 /* variable cannot be modified */
|
#define VREADONLY 0x02 /* variable cannot be modified */
|
||||||
#define VSTRFIXED 04 /* variable struct is staticly allocated */
|
#define VSTRFIXED 0x04 /* variable struct is staticly allocated */
|
||||||
#define VTEXTFIXED 010 /* text is staticly allocated */
|
#define VTEXTFIXED 0x08 /* text is staticly allocated */
|
||||||
#define VSTACK 020 /* text is allocated on the stack */
|
#define VSTACK 0x10 /* text is allocated on the stack */
|
||||||
#define VUNSET 040 /* the variable is not set */
|
#define VUNSET 0x20 /* the variable is not set */
|
||||||
|
#define VNOFUNC 0x40 /* don't call the callback function */
|
||||||
|
|
||||||
|
|
||||||
struct var {
|
struct var {
|
||||||
struct var *next; /* next entry in hash list */
|
struct var *next; /* next entry in hash list */
|
||||||
int flags; /* flags are defined above */
|
int flags; /* flags are defined above */
|
||||||
char *text; /* name=value */
|
char *text; /* name=value */
|
||||||
|
void (*func)(const char *);
|
||||||
|
/* function to be called when */
|
||||||
|
/* the variable gets set/unset */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -66,18 +67,16 @@ struct localvar {
|
||||||
|
|
||||||
struct localvar *localvars;
|
struct localvar *localvars;
|
||||||
|
|
||||||
#if ATTY
|
|
||||||
extern struct var vatty;
|
|
||||||
#endif
|
|
||||||
extern struct var vifs;
|
extern struct var vifs;
|
||||||
extern struct var vmail;
|
extern struct var vmail;
|
||||||
extern struct var vmpath;
|
extern struct var vmpath;
|
||||||
extern struct var vpath;
|
extern struct var vpath;
|
||||||
|
extern struct var vppid;
|
||||||
extern struct var vps1;
|
extern struct var vps1;
|
||||||
extern struct var vps2;
|
extern struct var vps2;
|
||||||
extern struct var vpse;
|
extern struct var vpse;
|
||||||
#if ATTY
|
#ifndef NO_HISTORY
|
||||||
extern struct var vterm;
|
extern struct var vhistsize;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -87,43 +86,39 @@ extern struct var vterm;
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define ifsval() (vifs.text + 4)
|
#define ifsval() (vifs.text + 4)
|
||||||
|
#define ifsset() ((vifs.flags & VUNSET) == 0)
|
||||||
#define mailval() (vmail.text + 5)
|
#define mailval() (vmail.text + 5)
|
||||||
#define mpathval() (vmpath.text + 9)
|
#define mpathval() (vmpath.text + 9)
|
||||||
#define pathval() (vpath.text + 5)
|
#define pathval() (vpath.text + 5)
|
||||||
#define ps1val() (vps1.text + 4)
|
#define ps1val() (vps1.text + 4)
|
||||||
#define ps2val() (vps2.text + 4)
|
#define ps2val() (vps2.text + 4)
|
||||||
#define pseval() (vpse.text + 4)
|
#define pseval() (vpse.text + 4)
|
||||||
#if ATTY
|
#define optindval() (voptind.text + 7)
|
||||||
#define termval() (vterm.text + 5)
|
#ifndef NO_HISTORY
|
||||||
|
#define histsizeval() (vhistsize.text + 9)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if ATTY
|
|
||||||
#define attyset() ((vatty.flags & VUNSET) == 0)
|
|
||||||
#endif
|
|
||||||
#define mpathset() ((vmpath.flags & VUNSET) == 0)
|
#define mpathset() ((vmpath.flags & VUNSET) == 0)
|
||||||
|
|
||||||
|
void initvar(void);
|
||||||
#ifdef __STDC__
|
|
||||||
void initvar();
|
|
||||||
void setvar(char *, char *, int);
|
void setvar(char *, char *, int);
|
||||||
void setvareq(char *, int);
|
void setvareq(char *, int);
|
||||||
struct strlist;
|
struct strlist;
|
||||||
void listsetvar(struct strlist *);
|
void listsetvar(struct strlist *);
|
||||||
char *lookupvar(char *);
|
char *lookupvar(char *);
|
||||||
char *bltinlookup(char *, int);
|
char *bltinlookup(char *, int);
|
||||||
char **environment();
|
char **environment(void);
|
||||||
|
void shprocvar(void);
|
||||||
int showvarscmd(int, char **);
|
int showvarscmd(int, char **);
|
||||||
|
int exportcmd(int, char **);
|
||||||
|
int localcmd(int, char **);
|
||||||
void mklocal(char *);
|
void mklocal(char *);
|
||||||
void poplocalvars(void);
|
void poplocalvars(void);
|
||||||
#else
|
int setvarcmd(int, char **);
|
||||||
void initvar();
|
int unsetcmd(int, char **);
|
||||||
void setvar();
|
int unsetvar(char *);
|
||||||
void setvareq();
|
int setvarsafe(char *, char *, int);
|
||||||
void listsetvar();
|
|
||||||
char *lookupvar();
|
/*
|
||||||
char *bltinlookup();
|
* $PchId: var.h,v 1.4 2006/03/29 12:04:45 philip Exp $
|
||||||
char **environment();
|
*/
|
||||||
int showvarscmd();
|
|
||||||
void mklocal();
|
|
||||||
void poplocalvars();
|
|
||||||
#endif
|
|
||||||
|
|
Loading…
Reference in a new issue